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 apps/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     # if (argv[1] == "test') run-tests()
      485     {
      486       # if (argc <= 1) break
      487       81 7/subop/compare *ebp 1/imm32
      488       7e/jump-if-<= break/disp8
      489       # if (argv[1] != "test") break
      490       (kernel-string-equal? *(ebp+8) "test")  # => eax
      491       3d/compare-eax-and 0/imm32/false
      492       74/jump-if-= break/disp8
      493       #
      494       (run-tests)
      495       # syscall(exit, *Num-test-failures)
      496       8b/-> *Num-test-failures 3/r32/ebx
      497       eb/jump $mu-main:end/disp8
      498     }
      499     # otherwise convert Stdin
      500     (convert-mu Stdin Stdout Stderr 0)
      501     (flush Stdout)
      502     # syscall(exit, 0)
      503     bb/copy-to-ebx 0/imm32
      504 $mu-main:end:
      505     e8/call syscall_exit/disp32
      506
      507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
      508     # . prologue
      509     55/push-ebp
      510     89/<- %ebp 4/r32/esp
      511     # . save registers
      512     50/push-eax
      513     # initialize global data structures
      514     c7 0/subop/copy *Next-block-index 1/imm32
      515     8b/-> *Primitive-type-ids 0/r32/eax
      516     89/<- *Type-id 0/r32/eax  # stream-write
      517     c7 0/subop/copy *_Program-functions 0/imm32
      518     c7 0/subop/copy *_Program-functions->payload 0/imm32
      519     c7 0/subop/copy *_Program-types 0/imm32
      520     c7 0/subop/copy *_Program-types->payload 0/imm32
      521     c7 0/subop/copy *_Program-signatures 0/imm32
      522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
      523     #
      524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
      525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
      526 #?     (dump-typeinfos "=== typeinfos\n")
      527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
      528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
      529 $convert-mu:end:
      530     # . restore registers
      531     58/pop-to-eax
      532     # . epilogue
      533     89/<- %esp 5/r32/ebp
      534     5d/pop-to-ebp
      535     c3/return
      536
      537 test-convert-empty-input:
      538     # empty input => empty output
      539     # . prologue
      540     55/push-ebp
      541     89/<- %ebp 4/r32/esp
      542     # setup
      543     (clear-stream _test-input-stream)
      544     (clear-stream $_test-input-buffered-file->buffer)
      545     (clear-stream _test-output-stream)
      546     (clear-stream $_test-output-buffered-file->buffer)
      547     #
      548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      549     (flush _test-output-buffered-file)
      550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
      551     # . epilogue
      552     89/<- %esp 5/r32/ebp
      553     5d/pop-to-ebp
      554     c3/return
      555
      556 test-convert-function-skeleton:
      557     # . prologue
      558     55/push-ebp
      559     89/<- %ebp 4/r32/esp
      560     # setup
      561     (clear-stream _test-input-stream)
      562     (clear-stream $_test-input-buffered-file->buffer)
      563     (clear-stream _test-output-stream)
      564     (clear-stream $_test-output-buffered-file->buffer)
      565     #
      566     (write _test-input-stream "fn foo {\n")
      567     (write _test-input-stream "}\n")
      568     # convert
      569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      570     (flush _test-output-buffered-file)
      571 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
      577     # check output
      578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
      579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
      580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
      581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
      582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
      583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
      584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
      585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
      586     # . epilogue
      587     89/<- %esp 5/r32/ebp
      588     5d/pop-to-ebp
      589     c3/return
      590
      591 test-convert-multiple-function-skeletons:
      592     # . prologue
      593     55/push-ebp
      594     89/<- %ebp 4/r32/esp
      595     # setup
      596     (clear-stream _test-input-stream)
      597     (clear-stream $_test-input-buffered-file->buffer)
      598     (clear-stream _test-output-stream)
      599     (clear-stream $_test-output-buffered-file->buffer)
      600     #
      601     (write _test-input-stream "fn foo {\n")
      602     (write _test-input-stream "}\n")
      603     (write _test-input-stream "fn bar {\n")
      604     (write _test-input-stream "}\n")
      605     # convert
      606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      607     (flush _test-output-buffered-file)
      608 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
      614     # check first function
      615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
      616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
      617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
      618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
      619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
      620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
      621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
      622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
      623     # check second function
      624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
      625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
      626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
      627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
      628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
      629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
      630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
      631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
      632     # . epilogue
      633     89/<- %esp 5/r32/ebp
      634     5d/pop-to-ebp
      635     c3/return
      636
      637 test-convert-function-with-arg:
      638     # . prologue
      639     55/push-ebp
      640     89/<- %ebp 4/r32/esp
      641     # setup
      642     (clear-stream _test-input-stream)
      643     (clear-stream $_test-input-buffered-file->buffer)
      644     (clear-stream _test-output-stream)
      645     (clear-stream $_test-output-buffered-file->buffer)
      646     #
      647     (write _test-input-stream "fn foo n: int {\n")
      648     (write _test-input-stream "}\n")
      649     # convert
      650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      651     (flush _test-output-buffered-file)
      652 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
      658     # check output
      659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
      660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
      661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
      662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
      663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
      664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
      665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
      666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
      667     # . epilogue
      668     89/<- %esp 5/r32/ebp
      669     5d/pop-to-ebp
      670     c3/return
      671
      672 test-function-with-redefined-name:
      673     # . prologue
      674     55/push-ebp
      675     89/<- %ebp 4/r32/esp
      676     # setup
      677     (clear-stream _test-input-stream)
      678     (clear-stream $_test-input-buffered-file->buffer)
      679     (clear-stream _test-output-stream)
      680     (clear-stream $_test-output-buffered-file->buffer)
      681     (clear-stream _test-error-stream)
      682     (clear-stream $_test-error-buffered-file->buffer)
      683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      684     68/push 0/imm32
      685     68/push 0/imm32
      686     89/<- %edx 4/r32/esp
      687     (tailor-exit-descriptor %edx 0x10)
      688     #
      689     (write _test-input-stream "fn foo {\n")
      690     (write _test-input-stream "}\n")
      691     (write _test-input-stream "fn foo {\n")
      692     (write _test-input-stream "}\n")
      693     # convert
      694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      695     # registers except esp clobbered at this point
      696     # restore ed
      697     89/<- %edx 4/r32/esp
      698     (flush _test-output-buffered-file)
      699     (flush _test-error-buffered-file)
      700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      706     # check output
      707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
      708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
      709     # check that stop(1) was called
      710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
      711     # don't restore from ebp
      712     81 0/subop/add %esp 8/imm32
      713     # . epilogue
      714     5d/pop-to-ebp
      715     c3/return
      716
      717 test-function-with-redefined-name-2:
      718     # . prologue
      719     55/push-ebp
      720     89/<- %ebp 4/r32/esp
      721     # setup
      722     (clear-stream _test-input-stream)
      723     (clear-stream $_test-input-buffered-file->buffer)
      724     (clear-stream _test-output-stream)
      725     (clear-stream $_test-output-buffered-file->buffer)
      726     (clear-stream _test-error-stream)
      727     (clear-stream $_test-error-buffered-file->buffer)
      728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      729     68/push 0/imm32
      730     68/push 0/imm32
      731     89/<- %edx 4/r32/esp
      732     (tailor-exit-descriptor %edx 0x10)
      733     #
      734     (write _test-input-stream "fn foo {\n")
      735     (write _test-input-stream "}\n")
      736     (write _test-input-stream "sig foo\n")
      737     # convert
      738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      739     # registers except esp clobbered at this point
      740     # restore ed
      741     89/<- %edx 4/r32/esp
      742     (flush _test-output-buffered-file)
      743     (flush _test-error-buffered-file)
      744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      750     # check output
      751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
      752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
      753     # check that stop(1) was called
      754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
      755     # don't restore from ebp
      756     81 0/subop/add %esp 8/imm32
      757     # . epilogue
      758     5d/pop-to-ebp
      759     c3/return
      760
      761 test-function-with-redefined-name-3:
      762     # . prologue
      763     55/push-ebp
      764     89/<- %ebp 4/r32/esp
      765     # setup
      766     (clear-stream _test-input-stream)
      767     (clear-stream $_test-input-buffered-file->buffer)
      768     (clear-stream _test-output-stream)
      769     (clear-stream $_test-output-buffered-file->buffer)
      770     (clear-stream _test-error-stream)
      771     (clear-stream $_test-error-buffered-file->buffer)
      772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      773     68/push 0/imm32
      774     68/push 0/imm32
      775     89/<- %edx 4/r32/esp
      776     (tailor-exit-descriptor %edx 0x10)
      777     #
      778     (write _test-input-stream "sig foo\n")
      779     (write _test-input-stream "fn foo {\n")
      780     (write _test-input-stream "}\n")
      781     # convert
      782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      783     # registers except esp clobbered at this point
      784     # restore ed
      785     89/<- %edx 4/r32/esp
      786     (flush _test-output-buffered-file)
      787     (flush _test-error-buffered-file)
      788 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      794     # check output
      795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
      796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
      797     # check that stop(1) was called
      798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
      799     # don't restore from ebp
      800     81 0/subop/add %esp 8/imm32
      801     # . epilogue
      802     5d/pop-to-ebp
      803     c3/return
      804
      805 test-function-with-inout-in-register:
      806     # . prologue
      807     55/push-ebp
      808     89/<- %ebp 4/r32/esp
      809     # setup
      810     (clear-stream _test-input-stream)
      811     (clear-stream $_test-input-buffered-file->buffer)
      812     (clear-stream _test-output-stream)
      813     (clear-stream $_test-output-buffered-file->buffer)
      814     (clear-stream _test-error-stream)
      815     (clear-stream $_test-error-buffered-file->buffer)
      816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      817     68/push 0/imm32
      818     68/push 0/imm32
      819     89/<- %edx 4/r32/esp
      820     (tailor-exit-descriptor %edx 0x10)
      821     #
      822     (write _test-input-stream "fn foo x/eax: int {\n")
      823     (write _test-input-stream "}\n")
      824     # convert
      825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      826     # registers except esp clobbered at this point
      827     # restore ed
      828     89/<- %edx 4/r32/esp
      829     (flush _test-output-buffered-file)
      830     (flush _test-error-buffered-file)
      831 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      837     # check output
      838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
      839     (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")
      840     # check that stop(1) was called
      841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
      842     # don't restore from ebp
      843     81 0/subop/add %esp 8/imm32
      844     # . epilogue
      845     5d/pop-to-ebp
      846     c3/return
      847
      848 test-function-with-addr-output:
      849     # . prologue
      850     55/push-ebp
      851     89/<- %ebp 4/r32/esp
      852     # setup
      853     (clear-stream _test-input-stream)
      854     (clear-stream $_test-input-buffered-file->buffer)
      855     (clear-stream _test-output-stream)
      856     (clear-stream $_test-output-buffered-file->buffer)
      857     (clear-stream _test-error-stream)
      858     (clear-stream $_test-error-buffered-file->buffer)
      859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      860     68/push 0/imm32
      861     68/push 0/imm32
      862     89/<- %edx 4/r32/esp
      863     (tailor-exit-descriptor %edx 0x10)
      864     #
      865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
      866     (write _test-input-stream "}\n")
      867     # convert
      868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      869     # registers except esp clobbered at this point
      870     # restore ed
      871     89/<- %edx 4/r32/esp
      872     (flush _test-output-buffered-file)
      873     (flush _test-error-buffered-file)
      874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      880     # check output
      881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
      882     (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")
      883     # check that stop(1) was called
      884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
      885     # don't restore from ebp
      886     81 0/subop/add %esp 8/imm32
      887     # . epilogue
      888     5d/pop-to-ebp
      889     c3/return
      890
      891 test-function-with-addr-inout:
      892     # . prologue
      893     55/push-ebp
      894     89/<- %ebp 4/r32/esp
      895     # setup
      896     (clear-stream _test-input-stream)
      897     (clear-stream $_test-input-buffered-file->buffer)
      898     (clear-stream _test-output-stream)
      899     (clear-stream $_test-output-buffered-file->buffer)
      900     (clear-stream _test-error-stream)
      901     (clear-stream $_test-error-buffered-file->buffer)
      902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      903     68/push 0/imm32
      904     68/push 0/imm32
      905     89/<- %edx 4/r32/esp
      906     (tailor-exit-descriptor %edx 0x10)
      907     #
      908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
      909     (write _test-input-stream "}\n")
      910     # convert
      911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      912     # registers except esp clobbered at this point
      913     # restore ed
      914     89/<- %edx 4/r32/esp
      915     (flush _test-output-buffered-file)
      916     (flush _test-error-buffered-file)
      917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      923     # check output
      924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
      925     (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")
      926     # check that stop(1) was called
      927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
      928     # don't restore from ebp
      929     81 0/subop/add %esp 8/imm32
      930     # . epilogue
      931     5d/pop-to-ebp
      932     c3/return
      933
      934 test-function-with-addr-inout-2:
      935     # . prologue
      936     55/push-ebp
      937     89/<- %ebp 4/r32/esp
      938     # setup
      939     (clear-stream _test-input-stream)
      940     (clear-stream $_test-input-buffered-file->buffer)
      941     (clear-stream _test-output-stream)
      942     (clear-stream $_test-output-buffered-file->buffer)
      943     (clear-stream _test-error-stream)
      944     (clear-stream $_test-error-buffered-file->buffer)
      945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      946     68/push 0/imm32
      947     68/push 0/imm32
      948     89/<- %edx 4/r32/esp
      949     (tailor-exit-descriptor %edx 0x10)
      950     #
      951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
      952     (write _test-input-stream "}\n")
      953     # convert
      954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      955     # registers except esp clobbered at this point
      956     # restore ed
      957     89/<- %edx 4/r32/esp
      958     (flush _test-output-buffered-file)
      959     (flush _test-error-buffered-file)
      960 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      966     # check output
      967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
      968     (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")
      969     # check that stop(1) was called
      970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
      971     # don't restore from ebp
      972     81 0/subop/add %esp 8/imm32
      973     # . epilogue
      974     5d/pop-to-ebp
      975     c3/return
      976
      977 test-function-with-addr-inout-3:
      978     # . prologue
      979     55/push-ebp
      980     89/<- %ebp 4/r32/esp
      981     # setup
      982     (clear-stream _test-input-stream)
      983     (clear-stream $_test-input-buffered-file->buffer)
      984     (clear-stream _test-output-stream)
      985     (clear-stream $_test-output-buffered-file->buffer)
      986     (clear-stream _test-error-stream)
      987     (clear-stream $_test-error-buffered-file->buffer)
      988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      989     68/push 0/imm32
      990     68/push 0/imm32
      991     89/<- %edx 4/r32/esp
      992     (tailor-exit-descriptor %edx 0x10)
      993     #
      994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
      995     (write _test-input-stream "}\n")
      996     # convert
      997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      998     # registers except esp clobbered at this point
      999     # restore ed
     1000     89/<- %edx 4/r32/esp
     1001     (flush _test-output-buffered-file)
     1002     (flush _test-error-buffered-file)
     1003 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1009     # check output
     1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
     1011     (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")
     1012     # check that stop(1) was called
     1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
     1014     # don't restore from ebp
     1015     81 0/subop/add %esp 8/imm32
     1016     # . epilogue
     1017     5d/pop-to-ebp
     1018     c3/return
     1019
     1020 test-function-with-addr-inout-4:
     1021     # . prologue
     1022     55/push-ebp
     1023     89/<- %ebp 4/r32/esp
     1024     # setup
     1025     (clear-stream _test-input-stream)
     1026     (clear-stream $_test-input-buffered-file->buffer)
     1027     (clear-stream _test-output-stream)
     1028     (clear-stream $_test-output-buffered-file->buffer)
     1029     (clear-stream _test-error-stream)
     1030     (clear-stream $_test-error-buffered-file->buffer)
     1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1032     68/push 0/imm32
     1033     68/push 0/imm32
     1034     89/<- %edx 4/r32/esp
     1035     (tailor-exit-descriptor %edx 0x10)
     1036     #
     1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
     1038     (write _test-input-stream "}\n")
     1039     # convert
     1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1041     # registers except esp clobbered at this point
     1042     # restore ed
     1043     89/<- %edx 4/r32/esp
     1044     (flush _test-output-buffered-file)
     1045     (flush _test-error-buffered-file)
     1046 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1052     # check output
     1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
     1054     (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")
     1055     # check that stop(1) was called
     1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
     1057     # don't restore from ebp
     1058     81 0/subop/add %esp 8/imm32
     1059     # . epilogue
     1060     5d/pop-to-ebp
     1061     c3/return
     1062
     1063 # 'main' is an exception
     1064 test-function-main-with-addr-inout:
     1065     # . prologue
     1066     55/push-ebp
     1067     89/<- %ebp 4/r32/esp
     1068     # setup
     1069     (clear-stream _test-input-stream)
     1070     (clear-stream $_test-input-buffered-file->buffer)
     1071     (clear-stream _test-output-stream)
     1072     (clear-stream $_test-output-buffered-file->buffer)
     1073     #
     1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
     1075     (write _test-input-stream "}\n")
     1076     # convert
     1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1078     (flush _test-output-buffered-file)
     1079     # no errors
     1080     # . epilogue
     1081     89/<- %esp 5/r32/ebp
     1082     5d/pop-to-ebp
     1083     c3/return
     1084
     1085 # 'lookup' is an exception, but only in signatures
     1086 test-signature-lookup-with-addr-inout:
     1087     # . prologue
     1088     55/push-ebp
     1089     89/<- %ebp 4/r32/esp
     1090     # setup
     1091     (clear-stream _test-input-stream)
     1092     (clear-stream $_test-input-buffered-file->buffer)
     1093     (clear-stream _test-output-stream)
     1094     (clear-stream $_test-output-buffered-file->buffer)
     1095     #
     1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
     1097     # convert
     1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1099     (flush _test-output-buffered-file)
     1100     # no errors
     1101     # . epilogue
     1102     89/<- %esp 5/r32/ebp
     1103     5d/pop-to-ebp
     1104     c3/return
     1105
     1106 test-convert-function-with-arg-and-body:
     1107     # . prologue
     1108     55/push-ebp
     1109     89/<- %ebp 4/r32/esp
     1110     # setup
     1111     (clear-stream _test-input-stream)
     1112     (clear-stream $_test-input-buffered-file->buffer)
     1113     (clear-stream _test-output-stream)
     1114     (clear-stream $_test-output-buffered-file->buffer)
     1115     #
     1116     (write _test-input-stream "fn foo n: int {\n")
     1117     (write _test-input-stream "  increment n\n")
     1118     (write _test-input-stream "}\n")
     1119     # convert
     1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1121     (flush _test-output-buffered-file)
     1122 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1128     # check output
     1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
     1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
     1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
     1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
     1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
     1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
     1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
     1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
     1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
     1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
     1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
     1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
     1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
     1142     # . epilogue
     1143     89/<- %esp 5/r32/ebp
     1144     5d/pop-to-ebp
     1145     c3/return
     1146
     1147 test-convert-function-distinguishes-args:
     1148     # . prologue
     1149     55/push-ebp
     1150     89/<- %ebp 4/r32/esp
     1151     # setup
     1152     (clear-stream _test-input-stream)
     1153     (clear-stream $_test-input-buffered-file->buffer)
     1154     (clear-stream _test-output-stream)
     1155     (clear-stream $_test-output-buffered-file->buffer)
     1156     #
     1157     (write _test-input-stream "fn foo a: int, b: int {\n")
     1158     (write _test-input-stream "  increment b\n")
     1159     (write _test-input-stream "}\n")
     1160     # convert
     1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1162     (flush _test-output-buffered-file)
     1163 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1169     # check output
     1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
     1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
     1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
     1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
     1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
     1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
     1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
     1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
     1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
     1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
     1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
     1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
     1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
     1183     # . epilogue
     1184     89/<- %esp 5/r32/ebp
     1185     5d/pop-to-ebp
     1186     c3/return
     1187
     1188 test-convert-function-with-return-literal:
     1189     # . prologue
     1190     55/push-ebp
     1191     89/<- %ebp 4/r32/esp
     1192     # setup
     1193     (clear-stream _test-input-stream)
     1194     (clear-stream $_test-input-buffered-file->buffer)
     1195     (clear-stream _test-output-stream)
     1196     (clear-stream $_test-output-buffered-file->buffer)
     1197     #
     1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1199     (write _test-input-stream "  return 0\n")
     1200     (write _test-input-stream "}\n")
     1201     # convert
     1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1203     (flush _test-output-buffered-file)
     1204 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1210     # check output
     1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
     1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
     1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
     1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
     1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
     1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
     1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
     1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
     1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
     1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
     1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
     1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
     1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
     1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
     1225     # . epilogue
     1226     89/<- %esp 5/r32/ebp
     1227     5d/pop-to-ebp
     1228     c3/return
     1229
     1230 test-convert-function-with-return:
     1231     # . prologue
     1232     55/push-ebp
     1233     89/<- %ebp 4/r32/esp
     1234     # setup
     1235     (clear-stream _test-input-stream)
     1236     (clear-stream $_test-input-buffered-file->buffer)
     1237     (clear-stream _test-output-stream)
     1238     (clear-stream $_test-output-buffered-file->buffer)
     1239     #
     1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1241     (write _test-input-stream "  var y: int\n")
     1242     (write _test-input-stream "  return y\n")
     1243     (write _test-input-stream "}\n")
     1244     # convert
     1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1246     (flush _test-output-buffered-file)
     1247 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1253     # check output
     1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
     1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
     1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
     1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
     1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
     1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
     1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
     1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
     1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
     1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
     1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
     1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
     1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
     1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
     1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
     1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
     1270     # . epilogue
     1271     89/<- %esp 5/r32/ebp
     1272     5d/pop-to-ebp
     1273     c3/return
     1274
     1275 test-convert-function-with-return-float:
     1276     # . prologue
     1277     55/push-ebp
     1278     89/<- %ebp 4/r32/esp
     1279     # setup
     1280     (clear-stream _test-input-stream)
     1281     (clear-stream $_test-input-buffered-file->buffer)
     1282     (clear-stream _test-output-stream)
     1283     (clear-stream $_test-output-buffered-file->buffer)
     1284     #
     1285     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
     1286     (write _test-input-stream "  var y: float\n")
     1287     (write _test-input-stream "  return y\n")
     1288     (write _test-input-stream "}\n")
     1289     # convert
     1290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1291     (flush _test-output-buffered-file)
     1292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1298     # check output
     1299     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
     1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
     1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
     1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
     1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
     1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
     1305     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
     1306     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
     1307     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
     1308     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
     1309     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
     1310     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
     1311     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
     1312     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
     1313     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
     1314     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
     1315     # . epilogue
     1316     89/<- %esp 5/r32/ebp
     1317     5d/pop-to-ebp
     1318     c3/return
     1319
     1320 test-convert-function-with-return-register:
     1321     # . prologue
     1322     55/push-ebp
     1323     89/<- %ebp 4/r32/esp
     1324     # setup
     1325     (clear-stream _test-input-stream)
     1326     (clear-stream $_test-input-buffered-file->buffer)
     1327     (clear-stream _test-output-stream)
     1328     (clear-stream $_test-output-buffered-file->buffer)
     1329     #
     1330     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1331     (write _test-input-stream "  var y/eax: int <- copy 3\n")
     1332     (write _test-input-stream "  return y\n")
     1333     (write _test-input-stream "}\n")
     1334     # convert
     1335     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1336     (flush _test-output-buffered-file)
     1337 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1343     # check output
     1344     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
     1345     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
     1346     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
     1347     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
     1348     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
     1349     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
     1350     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
     1351     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
     1352     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
     1353     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
     1354     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
     1355     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
     1356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
     1357     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
     1358     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
     1359     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
     1360     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
     1361     # . epilogue
     1362     89/<- %esp 5/r32/ebp
     1363     5d/pop-to-ebp
     1364     c3/return
     1365
     1366 test-function-with-output-without-register:
     1367     # . prologue
     1368     55/push-ebp
     1369     89/<- %ebp 4/r32/esp
     1370     # setup
     1371     (clear-stream _test-input-stream)
     1372     (clear-stream $_test-input-buffered-file->buffer)
     1373     (clear-stream _test-output-stream)
     1374     (clear-stream $_test-output-buffered-file->buffer)
     1375     (clear-stream _test-error-stream)
     1376     (clear-stream $_test-error-buffered-file->buffer)
     1377     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1378     68/push 0/imm32
     1379     68/push 0/imm32
     1380     89/<- %edx 4/r32/esp
     1381     (tailor-exit-descriptor %edx 0x10)
     1382     #
     1383     (write _test-input-stream "fn foo -> _: int {\n")
     1384     (write _test-input-stream "}\n")
     1385     # convert
     1386     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1387     # registers except esp clobbered at this point
     1388     # restore ed
     1389     89/<- %edx 4/r32/esp
     1390     (flush _test-output-buffered-file)
     1391     (flush _test-error-buffered-file)
     1392 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1398     # check output
     1399     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
     1400     (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")
     1401     # check that stop(1) was called
     1402     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
     1403     # don't restore from ebp
     1404     81 0/subop/add %esp 8/imm32
     1405     # . epilogue
     1406     5d/pop-to-ebp
     1407     c3/return
     1408
     1409 test-function-with-outputs-in-conflicting-registers:
     1410     # . prologue
     1411     55/push-ebp
     1412     89/<- %ebp 4/r32/esp
     1413     # setup
     1414     (clear-stream _test-input-stream)
     1415     (clear-stream $_test-input-buffered-file->buffer)
     1416     (clear-stream _test-output-stream)
     1417     (clear-stream $_test-output-buffered-file->buffer)
     1418     (clear-stream _test-error-stream)
     1419     (clear-stream $_test-error-buffered-file->buffer)
     1420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1421     68/push 0/imm32
     1422     68/push 0/imm32
     1423     89/<- %edx 4/r32/esp
     1424     (tailor-exit-descriptor %edx 0x10)
     1425     #
     1426     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
     1427     (write _test-input-stream "}\n")
     1428     # convert
     1429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1430     # registers except esp clobbered at this point
     1431     # restore ed
     1432     89/<- %edx 4/r32/esp
     1433     (flush _test-output-buffered-file)
     1434     (flush _test-error-buffered-file)
     1435 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1441     # check output
     1442     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
     1443     (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")
     1444     # check that stop(1) was called
     1445     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
     1446     # don't restore from ebp
     1447     81 0/subop/add %esp 8/imm32
     1448     # . epilogue
     1449     5d/pop-to-ebp
     1450     c3/return
     1451
     1452 test-function-with-named-output:
     1453     # . prologue
     1454     55/push-ebp
     1455     89/<- %ebp 4/r32/esp
     1456     # setup
     1457     (clear-stream _test-input-stream)
     1458     (clear-stream $_test-input-buffered-file->buffer)
     1459     (clear-stream _test-output-stream)
     1460     (clear-stream $_test-output-buffered-file->buffer)
     1461     (clear-stream _test-error-stream)
     1462     (clear-stream $_test-error-buffered-file->buffer)
     1463     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1464     68/push 0/imm32
     1465     68/push 0/imm32
     1466     89/<- %edx 4/r32/esp
     1467     (tailor-exit-descriptor %edx 0x10)
     1468     #
     1469     (write _test-input-stream "fn foo -> x/eax: int {\n")
     1470     (write _test-input-stream "  return 0\n")
     1471     (write _test-input-stream "}\n")
     1472     # convert
     1473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1474     # registers except esp clobbered at this point
     1475     # restore ed
     1476     89/<- %edx 4/r32/esp
     1477     (flush _test-output-buffered-file)
     1478     (flush _test-error-buffered-file)
     1479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1485     # check output
     1486     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
     1487     (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")
     1488     # check that stop(1) was called
     1489     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
     1490     # don't restore from ebp
     1491     81 0/subop/add %esp 8/imm32
     1492     # . epilogue
     1493     5d/pop-to-ebp
     1494     c3/return
     1495
     1496 test-return-with-wrong-type:
     1497     # . prologue
     1498     55/push-ebp
     1499     89/<- %ebp 4/r32/esp
     1500     # setup
     1501     (clear-stream _test-input-stream)
     1502     (clear-stream $_test-input-buffered-file->buffer)
     1503     (clear-stream _test-output-stream)
     1504     (clear-stream $_test-output-buffered-file->buffer)
     1505     (clear-stream _test-error-stream)
     1506     (clear-stream $_test-error-buffered-file->buffer)
     1507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1508     68/push 0/imm32
     1509     68/push 0/imm32
     1510     89/<- %edx 4/r32/esp
     1511     (tailor-exit-descriptor %edx 0x10)
     1512     #
     1513     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1514     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     1515     (write _test-input-stream "  return x\n")
     1516     (write _test-input-stream "}\n")
     1517     # convert
     1518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1519     # registers except esp clobbered at this point
     1520     # restore ed
     1521     89/<- %edx 4/r32/esp
     1522     (flush _test-output-buffered-file)
     1523     (flush _test-error-buffered-file)
     1524 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1530     # check output
     1531     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
     1532     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
     1533     # check that stop(1) was called
     1534     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
     1535     # don't restore from ebp
     1536     81 0/subop/add %esp 8/imm32
     1537     # . epilogue
     1538     5d/pop-to-ebp
     1539     c3/return
     1540
     1541 test-missing-return:
     1542     # . prologue
     1543     55/push-ebp
     1544     89/<- %ebp 4/r32/esp
     1545     # setup
     1546     (clear-stream _test-input-stream)
     1547     (clear-stream $_test-input-buffered-file->buffer)
     1548     (clear-stream _test-output-stream)
     1549     (clear-stream $_test-output-buffered-file->buffer)
     1550     (clear-stream _test-error-stream)
     1551     (clear-stream $_test-error-buffered-file->buffer)
     1552     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1553     68/push 0/imm32
     1554     68/push 0/imm32
     1555     89/<- %edx 4/r32/esp
     1556     (tailor-exit-descriptor %edx 0x10)
     1557     #
     1558     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1559     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     1560     (write _test-input-stream "}\n")
     1561     # convert
     1562     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1563     # registers except esp clobbered at this point
     1564     # restore ed
     1565     89/<- %edx 4/r32/esp
     1566     (flush _test-output-buffered-file)
     1567     (flush _test-error-buffered-file)
     1568 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1574     # check output
     1575     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
     1576     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
     1577     # check that stop(1) was called
     1578     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
     1579     # don't restore from ebp
     1580     81 0/subop/add %esp 8/imm32
     1581     # . epilogue
     1582     5d/pop-to-ebp
     1583     c3/return
     1584
     1585 test-missing-return-2:
     1586     # . prologue
     1587     55/push-ebp
     1588     89/<- %ebp 4/r32/esp
     1589     # setup
     1590     (clear-stream _test-input-stream)
     1591     (clear-stream $_test-input-buffered-file->buffer)
     1592     (clear-stream _test-output-stream)
     1593     (clear-stream $_test-output-buffered-file->buffer)
     1594     (clear-stream _test-error-stream)
     1595     (clear-stream $_test-error-buffered-file->buffer)
     1596     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1597     68/push 0/imm32
     1598     68/push 0/imm32
     1599     89/<- %edx 4/r32/esp
     1600     (tailor-exit-descriptor %edx 0x10)
     1601     #
     1602     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1603     (write _test-input-stream "}\n")
     1604     # convert
     1605     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1606     # registers except esp clobbered at this point
     1607     # restore ed
     1608     89/<- %edx 4/r32/esp
     1609     (flush _test-output-buffered-file)
     1610     (flush _test-error-buffered-file)
     1611 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1617     # check output
     1618     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
     1619     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
     1620     # check that stop(1) was called
     1621     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
     1622     # don't restore from ebp
     1623     81 0/subop/add %esp 8/imm32
     1624     # . epilogue
     1625     5d/pop-to-ebp
     1626     c3/return
     1627
     1628 test-early-exit-without-return:
     1629     # . prologue
     1630     55/push-ebp
     1631     89/<- %ebp 4/r32/esp
     1632     # setup
     1633     (clear-stream _test-input-stream)
     1634     (clear-stream $_test-input-buffered-file->buffer)
     1635     (clear-stream _test-output-stream)
     1636     (clear-stream $_test-output-buffered-file->buffer)
     1637     (clear-stream _test-error-stream)
     1638     (clear-stream $_test-error-buffered-file->buffer)
     1639     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1640     68/push 0/imm32
     1641     68/push 0/imm32
     1642     89/<- %edx 4/r32/esp
     1643     (tailor-exit-descriptor %edx 0x10)
     1644     #
     1645     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1646     (write _test-input-stream "  break\n")
     1647     (write _test-input-stream "  return 0\n")
     1648     (write _test-input-stream "}\n")
     1649     # convert
     1650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1651     # registers except esp clobbered at this point
     1652     # restore ed
     1653     89/<- %edx 4/r32/esp
     1654     (flush _test-output-buffered-file)
     1655     (flush _test-error-buffered-file)
     1656 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1662     # check output
     1663     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
     1664     (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")
     1665     # check that stop(1) was called
     1666     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
     1667     # don't restore from ebp
     1668     81 0/subop/add %esp 8/imm32
     1669     # . epilogue
     1670     5d/pop-to-ebp
     1671     c3/return
     1672
     1673 test-return-with-too-few-inouts:
     1674     # . prologue
     1675     55/push-ebp
     1676     89/<- %ebp 4/r32/esp
     1677     # setup
     1678     (clear-stream _test-input-stream)
     1679     (clear-stream $_test-input-buffered-file->buffer)
     1680     (clear-stream _test-output-stream)
     1681     (clear-stream $_test-output-buffered-file->buffer)
     1682     (clear-stream _test-error-stream)
     1683     (clear-stream $_test-error-buffered-file->buffer)
     1684     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1685     68/push 0/imm32
     1686     68/push 0/imm32
     1687     89/<- %edx 4/r32/esp
     1688     (tailor-exit-descriptor %edx 0x10)
     1689     #
     1690     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1691     (write _test-input-stream "  return\n")
     1692     (write _test-input-stream "}\n")
     1693     # convert
     1694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1695     # registers except esp clobbered at this point
     1696     # restore ed
     1697     89/<- %edx 4/r32/esp
     1698     (flush _test-output-buffered-file)
     1699     (flush _test-error-buffered-file)
     1700 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1706     # check output
     1707     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
     1708     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
     1709     # check that stop(1) was called
     1710     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
     1711     # don't restore from ebp
     1712     81 0/subop/add %esp 8/imm32
     1713     # . epilogue
     1714     5d/pop-to-ebp
     1715     c3/return
     1716
     1717 test-return-with-too-many-inouts:
     1718     # . prologue
     1719     55/push-ebp
     1720     89/<- %ebp 4/r32/esp
     1721     # setup
     1722     (clear-stream _test-input-stream)
     1723     (clear-stream $_test-input-buffered-file->buffer)
     1724     (clear-stream _test-output-stream)
     1725     (clear-stream $_test-output-buffered-file->buffer)
     1726     (clear-stream _test-error-stream)
     1727     (clear-stream $_test-error-buffered-file->buffer)
     1728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1729     68/push 0/imm32
     1730     68/push 0/imm32
     1731     89/<- %edx 4/r32/esp
     1732     (tailor-exit-descriptor %edx 0x10)
     1733     #
     1734     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1735     (write _test-input-stream "  return 0, 0\n")
     1736     (write _test-input-stream "}\n")
     1737     # convert
     1738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1739     # registers except esp clobbered at this point
     1740     # restore ed
     1741     89/<- %edx 4/r32/esp
     1742     (flush _test-output-buffered-file)
     1743     (flush _test-error-buffered-file)
     1744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1750     # check output
     1751     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
     1752     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
     1753     # check that stop(1) was called
     1754     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
     1755     # don't restore from ebp
     1756     81 0/subop/add %esp 8/imm32
     1757     # . epilogue
     1758     5d/pop-to-ebp
     1759     c3/return
     1760
     1761 test-return-unavailable-value:
     1762     # . prologue
     1763     55/push-ebp
     1764     89/<- %ebp 4/r32/esp
     1765     # setup
     1766     (clear-stream _test-input-stream)
     1767     (clear-stream $_test-input-buffered-file->buffer)
     1768     (clear-stream _test-output-stream)
     1769     (clear-stream $_test-output-buffered-file->buffer)
     1770     (clear-stream _test-error-stream)
     1771     (clear-stream $_test-error-buffered-file->buffer)
     1772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1773     68/push 0/imm32
     1774     68/push 0/imm32
     1775     89/<- %edx 4/r32/esp
     1776     (tailor-exit-descriptor %edx 0x10)
     1777     #
     1778     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
     1779     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     1780     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
     1781     (write _test-input-stream "  return y, x\n")
     1782     (write _test-input-stream "}\n")
     1783     # convert
     1784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1785     # registers except esp clobbered at this point
     1786     # restore ed
     1787     89/<- %edx 4/r32/esp
     1788     (flush _test-output-buffered-file)
     1789     (flush _test-error-buffered-file)
     1790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1796     # check output
     1797     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
     1798     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
     1799     # check that stop(1) was called
     1800     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
     1801     # don't restore from ebp
     1802     81 0/subop/add %esp 8/imm32
     1803     # . epilogue
     1804     5d/pop-to-ebp
     1805     c3/return
     1806
     1807 test-return-literal-to-float:
     1808     # . prologue
     1809     55/push-ebp
     1810     89/<- %ebp 4/r32/esp
     1811     # setup
     1812     (clear-stream _test-input-stream)
     1813     (clear-stream $_test-input-buffered-file->buffer)
     1814     (clear-stream _test-output-stream)
     1815     (clear-stream $_test-output-buffered-file->buffer)
     1816     (clear-stream _test-error-stream)
     1817     (clear-stream $_test-error-buffered-file->buffer)
     1818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1819     68/push 0/imm32
     1820     68/push 0/imm32
     1821     89/<- %edx 4/r32/esp
     1822     (tailor-exit-descriptor %edx 0x10)
     1823     #
     1824     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
     1825     (write _test-input-stream "  return 0\n")
     1826     (write _test-input-stream "}\n")
     1827     # convert
     1828     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1829     # registers except esp clobbered at this point
     1830     # restore ed
     1831     89/<- %edx 4/r32/esp
     1832     (flush _test-output-buffered-file)
     1833     (flush _test-error-buffered-file)
     1834 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1840     # check output
     1841     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
     1842     (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")
     1843     # check that stop(1) was called
     1844     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
     1845     # don't restore from ebp
     1846     81 0/subop/add %esp 8/imm32
     1847     # . epilogue
     1848     5d/pop-to-ebp
     1849     c3/return
     1850
     1851 test-convert-return-with-duplicate-values:
     1852     # . prologue
     1853     55/push-ebp
     1854     89/<- %ebp 4/r32/esp
     1855     # setup
     1856     (clear-stream _test-input-stream)
     1857     (clear-stream $_test-input-buffered-file->buffer)
     1858     (clear-stream _test-output-stream)
     1859     (clear-stream $_test-output-buffered-file->buffer)
     1860     #
     1861     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
     1862     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
     1863     (write _test-input-stream "  return x, x\n")
     1864     (write _test-input-stream "}\n")
     1865     # convert
     1866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1867     (flush _test-output-buffered-file)
     1868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1874     # check output
     1875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
     1876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
     1877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
     1878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
     1879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
     1880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
     1881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
     1882     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
     1883     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
     1884     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
     1885     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
     1886     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
     1887     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
     1888     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
     1889     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
     1890     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
     1891     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
     1892     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
     1893     # . epilogue
     1894     89/<- %esp 5/r32/ebp
     1895     5d/pop-to-ebp
     1896     c3/return
     1897
     1898 test-convert-return-with-duplicate-values-2:
     1899     # . prologue
     1900     55/push-ebp
     1901     89/<- %ebp 4/r32/esp
     1902     # setup
     1903     (clear-stream _test-input-stream)
     1904     (clear-stream $_test-input-buffered-file->buffer)
     1905     (clear-stream _test-output-stream)
     1906     (clear-stream $_test-output-buffered-file->buffer)
     1907     #
     1908     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
     1909     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
     1910     (write _test-input-stream "  return x, x\n")
     1911     (write _test-input-stream "}\n")
     1912     # convert
     1913     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1914     (flush _test-output-buffered-file)
     1915 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1921     # check output
     1922     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
     1923     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
     1924     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
     1925     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
     1926     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
     1927     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
     1928     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
     1929     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
     1930     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
     1931     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
     1932     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
     1933     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
     1934     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
     1935     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
     1936     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
     1937     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
     1938     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
     1939     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
     1940     # . epilogue
     1941     89/<- %esp 5/r32/ebp
     1942     5d/pop-to-ebp
     1943     c3/return
     1944
     1945 test-stmt-with-unknown-var:
     1946     # . prologue
     1947     55/push-ebp
     1948     89/<- %ebp 4/r32/esp
     1949     # setup
     1950     (clear-stream _test-input-stream)
     1951     (clear-stream $_test-input-buffered-file->buffer)
     1952     (clear-stream _test-output-stream)
     1953     (clear-stream $_test-output-buffered-file->buffer)
     1954     (clear-stream _test-error-stream)
     1955     (clear-stream $_test-error-buffered-file->buffer)
     1956     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1957     68/push 0/imm32
     1958     68/push 0/imm32
     1959     89/<- %edx 4/r32/esp
     1960     (tailor-exit-descriptor %edx 0x10)
     1961     #
     1962     (write _test-input-stream "fn foo {\n")
     1963     (write _test-input-stream "  x <- copy 0x34\n")
     1964     (write _test-input-stream "}\n")
     1965     # convert
     1966     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1967     # registers except esp clobbered at this point
     1968     # restore ed
     1969     89/<- %edx 4/r32/esp
     1970     (flush _test-output-buffered-file)
     1971     (flush _test-error-buffered-file)
     1972 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1978     # check output
     1979     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
     1980     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
     1981     # check that stop(1) was called
     1982     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
     1983     # don't restore from ebp
     1984     81 0/subop/add %esp 8/imm32
     1985     # . epilogue
     1986     5d/pop-to-ebp
     1987     c3/return
     1988
     1989 test-stmt-with-invalid-identifier:
     1990     # . prologue
     1991     55/push-ebp
     1992     89/<- %ebp 4/r32/esp
     1993     # setup
     1994     (clear-stream _test-input-stream)
     1995     (clear-stream $_test-input-buffered-file->buffer)
     1996     (clear-stream _test-output-stream)
     1997     (clear-stream $_test-output-buffered-file->buffer)
     1998     (clear-stream _test-error-stream)
     1999     (clear-stream $_test-error-buffered-file->buffer)
     2000     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2001     68/push 0/imm32
     2002     68/push 0/imm32
     2003     89/<- %edx 4/r32/esp
     2004     (tailor-exit-descriptor %edx 0x10)
     2005     #
     2006     (write _test-input-stream "fn foo {\n")
     2007     (write _test-input-stream "  1 <- copy 0x34\n")
     2008     (write _test-input-stream "}\n")
     2009     # convert
     2010     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2011     # registers except esp clobbered at this point
     2012     # restore ed
     2013     89/<- %edx 4/r32/esp
     2014     (flush _test-output-buffered-file)
     2015     (flush _test-error-buffered-file)
     2016 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2022     # check output
     2023     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
     2024     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
     2025     # check that stop(1) was called
     2026     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
     2027     # don't restore from ebp
     2028     81 0/subop/add %esp 8/imm32
     2029     # . epilogue
     2030     5d/pop-to-ebp
     2031     c3/return
     2032
     2033 test-stmt-with-deref-var:
     2034     # . prologue
     2035     55/push-ebp
     2036     89/<- %ebp 4/r32/esp
     2037     # setup
     2038     (clear-stream _test-input-stream)
     2039     (clear-stream $_test-input-buffered-file->buffer)
     2040     (clear-stream _test-output-stream)
     2041     (clear-stream $_test-output-buffered-file->buffer)
     2042     (clear-stream _test-error-stream)
     2043     (clear-stream $_test-error-buffered-file->buffer)
     2044     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2045     68/push 0/imm32
     2046     68/push 0/imm32
     2047     89/<- %edx 4/r32/esp
     2048     (tailor-exit-descriptor %edx 0x10)
     2049     #
     2050     (write _test-input-stream "fn foo {\n")
     2051     (write _test-input-stream "  *x <- copy 0x34\n")
     2052     (write _test-input-stream "}\n")
     2053     # convert
     2054     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2055     # registers except esp clobbered at this point
     2056     # restore ed
     2057     89/<- %edx 4/r32/esp
     2058     (flush _test-output-buffered-file)
     2059     (flush _test-error-buffered-file)
     2060 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2066     # check output
     2067     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
     2068     (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")
     2069     # check that stop(1) was called
     2070     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
     2071     # don't restore from ebp
     2072     81 0/subop/add %esp 8/imm32
     2073     # . epilogue
     2074     5d/pop-to-ebp
     2075     c3/return
     2076
     2077 test-convert-function-with-literal-arg:
     2078     # . prologue
     2079     55/push-ebp
     2080     89/<- %ebp 4/r32/esp
     2081     # setup
     2082     (clear-stream _test-input-stream)
     2083     (clear-stream $_test-input-buffered-file->buffer)
     2084     (clear-stream _test-output-stream)
     2085     (clear-stream $_test-output-buffered-file->buffer)
     2086     #
     2087     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
     2088     (write _test-input-stream "  var result/eax: int <- copy a\n")
     2089     (write _test-input-stream "  result <- add 1\n")
     2090     (write _test-input-stream "  return result\n")
     2091     (write _test-input-stream "}\n")
     2092     # convert
     2093     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2094     (flush _test-output-buffered-file)
     2095 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2101     # check output
     2102     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
     2103     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
     2104     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
     2105     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
     2106     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
     2107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
     2108     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
     2109     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
     2110     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
     2111     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
     2112     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
     2113     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
     2114     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
     2115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
     2116     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
     2117     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
     2118     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
     2119     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
     2120     # . epilogue
     2121     89/<- %esp 5/r32/ebp
     2122     5d/pop-to-ebp
     2123     c3/return
     2124
     2125 test-convert-function-with-literal-arg-2:
     2126     # . prologue
     2127     55/push-ebp
     2128     89/<- %ebp 4/r32/esp
     2129     # setup
     2130     (clear-stream _test-input-stream)
     2131     (clear-stream $_test-input-buffered-file->buffer)
     2132     (clear-stream _test-output-stream)
     2133     (clear-stream $_test-output-buffered-file->buffer)
     2134     #
     2135     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
     2136     (write _test-input-stream "  var result/ebx: int <- copy a\n")
     2137     (write _test-input-stream "  result <- add 1\n")
     2138     (write _test-input-stream "  return result\n")
     2139     (write _test-input-stream "}\n")
     2140     # convert
     2141     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2142     (flush _test-output-buffered-file)
     2143 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2149     # check output
     2150     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
     2151     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
     2152     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
     2153     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
     2154     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
     2155     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
     2156     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
     2157     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
     2158     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
     2159     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
     2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
     2161     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
     2162     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
     2163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
     2164     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
     2165     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
     2166     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
     2167     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
     2168     # . epilogue
     2169     89/<- %esp 5/r32/ebp
     2170     5d/pop-to-ebp
     2171     c3/return
     2172
     2173 test-convert-function-call-with-literal-arg:
     2174     # . prologue
     2175     55/push-ebp
     2176     89/<- %ebp 4/r32/esp
     2177     # setup
     2178     (clear-stream _test-input-stream)
     2179     (clear-stream $_test-input-buffered-file->buffer)
     2180     (clear-stream _test-output-stream)
     2181     (clear-stream $_test-output-buffered-file->buffer)
     2182     #
     2183     (write _test-input-stream "fn main -> _/ebx: int {\n")
     2184     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
     2185     (write _test-input-stream "  return result\n")
     2186     (write _test-input-stream "}\n")
     2187     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
     2188     (write _test-input-stream "  var result/eax: int <- copy a\n")
     2189     (write _test-input-stream "  result <- add b\n")
     2190     (write _test-input-stream "  return result\n")
     2191     (write _test-input-stream "}\n")
     2192     # convert
     2193     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2194     (flush _test-output-buffered-file)
     2195 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2201     # check output
     2202     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
     2203     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
     2204     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
     2205     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
     2206     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
     2207     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
     2208     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
     2209     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
     2210     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     2211     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
     2212     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     2213     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
     2214     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
     2215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
     2216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
     2217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
     2218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
     2219     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
     2220     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
     2221     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
     2222     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
     2223     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
     2224     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
     2225     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
     2226     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
     2227     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
     2228     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
     2229     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     2230     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
     2231     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
     2232     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
     2233     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
     2234     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
     2235     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
     2236     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
     2237     # . epilogue
     2238     89/<- %esp 5/r32/ebp
     2239     5d/pop-to-ebp
     2240     c3/return
     2241
     2242 test-convert-function-call-with-literal-string-arg:
     2243     # . prologue
     2244     55/push-ebp
     2245     89/<- %ebp 4/r32/esp
     2246     # setup
     2247     (clear-stream _test-input-stream)
     2248     (clear-stream $_test-input-buffered-file->buffer)
     2249     (clear-stream _test-output-stream)
     2250     (clear-stream $_test-output-buffered-file->buffer)
     2251     #
     2252     (write _test-input-stream "fn foo {\n")
     2253     (write _test-input-stream "  string-func \"abc\"\n")
     2254     (write _test-input-stream "}\n")
     2255     (write _test-input-stream "sig string-func in: (addr array byte)\n")
     2256     # convert
     2257     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2258     # no errors
     2259     # not bothering checking output
     2260     # . epilogue
     2261     89/<- %esp 5/r32/ebp
     2262     5d/pop-to-ebp
     2263     c3/return
     2264
     2265 test-convert-function-call-with-null-addr:
     2266     # . prologue
     2267     55/push-ebp
     2268     89/<- %ebp 4/r32/esp
     2269     # setup
     2270     (clear-stream _test-input-stream)
     2271     (clear-stream $_test-input-buffered-file->buffer)
     2272     (clear-stream _test-output-stream)
     2273     (clear-stream $_test-output-buffered-file->buffer)
     2274     #
     2275     (write _test-input-stream "fn foo {\n")
     2276     (write _test-input-stream "  bar 0\n")
     2277     (write _test-input-stream "}\n")
     2278     (write _test-input-stream "sig bar in: (addr int)\n")
     2279     # convert
     2280     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2281     # no errors
     2282     # not bothering checking output
     2283     # . epilogue
     2284     89/<- %esp 5/r32/ebp
     2285     5d/pop-to-ebp
     2286     c3/return
     2287
     2288 test-convert-function-call-with-signature:
     2289     # . prologue
     2290     55/push-ebp
     2291     89/<- %ebp 4/r32/esp
     2292     # setup
     2293     (clear-stream _test-input-stream)
     2294     (clear-stream $_test-input-buffered-file->buffer)
     2295     (clear-stream _test-output-stream)
     2296     (clear-stream $_test-output-buffered-file->buffer)
     2297     #
     2298     (write _test-input-stream "fn main -> _/ebx: int {\n")
     2299     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
     2300     (write _test-input-stream "  return result\n")
     2301     (write _test-input-stream "}\n")
     2302     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
     2303     # convert
     2304     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2305     (flush _test-output-buffered-file)
     2306 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2312     # check output
     2313     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
     2314     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
     2315     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
     2316     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
     2317     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
     2318     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
     2319     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
     2320     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
     2321     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     2322     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
     2323     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     2324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
     2325     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
     2326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
     2327     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
     2328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
     2329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
     2330     # . epilogue
     2331     89/<- %esp 5/r32/ebp
     2332     5d/pop-to-ebp
     2333     c3/return
     2334
     2335 test-convert-function-with-local-var-in-mem:
     2336     # . prologue
     2337     55/push-ebp
     2338     89/<- %ebp 4/r32/esp
     2339     # setup
     2340     (clear-stream _test-input-stream)
     2341     (clear-stream $_test-input-buffered-file->buffer)
     2342     (clear-stream _test-output-stream)
     2343     (clear-stream $_test-output-buffered-file->buffer)
     2344     #
     2345     (write _test-input-stream "fn foo {\n")
     2346     (write _test-input-stream "  var x: int\n")
     2347     (write _test-input-stream "  increment x\n")
     2348     (write _test-input-stream "}\n")
     2349     # convert
     2350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2351     (flush _test-output-buffered-file)
     2352 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2358     # check output
     2359     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
     2360     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
     2361     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
     2362     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
     2363     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
     2364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
     2365     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
     2366     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
     2367     (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")
     2368     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
     2369     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
     2370     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
     2371     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
     2372     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
     2373     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
     2374     # . epilogue
     2375     89/<- %esp 5/r32/ebp
     2376     5d/pop-to-ebp
     2377     c3/return
     2378
     2379 test-convert-invalid-literal:
     2380     # . prologue
     2381     55/push-ebp
     2382     89/<- %ebp 4/r32/esp
     2383     # setup
     2384     (clear-stream _test-input-stream)
     2385     (clear-stream $_test-input-buffered-file->buffer)
     2386     (clear-stream _test-output-stream)
     2387     (clear-stream $_test-output-buffered-file->buffer)
     2388     (clear-stream _test-error-stream)
     2389     (clear-stream $_test-error-buffered-file->buffer)
     2390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2391     68/push 0/imm32
     2392     68/push 0/imm32
     2393     89/<- %edx 4/r32/esp
     2394     (tailor-exit-descriptor %edx 0x10)
     2395     #
     2396     (write _test-input-stream "fn foo {\n")
     2397     (write _test-input-stream "  increment 1n\n")
     2398     (write _test-input-stream "}\n")
     2399     # convert
     2400     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2401     # registers except esp clobbered at this point
     2402     # restore ed
     2403     89/<- %edx 4/r32/esp
     2404     (flush _test-output-buffered-file)
     2405     (flush _test-error-buffered-file)
     2406 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2412     # check output
     2413     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
     2414     (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")
     2415     # check that stop(1) was called
     2416     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
     2417     # don't restore from ebp
     2418     81 0/subop/add %esp 8/imm32
     2419     # . epilogue
     2420     5d/pop-to-ebp
     2421     c3/return
     2422
     2423 test-convert-valid-literal-with-metadata:
     2424     # . prologue
     2425     55/push-ebp
     2426     89/<- %ebp 4/r32/esp
     2427     # setup
     2428     (clear-stream _test-input-stream)
     2429     (clear-stream $_test-input-buffered-file->buffer)
     2430     (clear-stream _test-output-stream)
     2431     (clear-stream $_test-output-buffered-file->buffer)
     2432     #
     2433     (write _test-input-stream "fn foo {\n")
     2434     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
     2435     (write _test-input-stream "}\n")
     2436     # convert
     2437     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2438     (flush _test-output-buffered-file)
     2439 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2445     # no errors
     2446     # . epilogue
     2447     89/<- %esp 5/r32/ebp
     2448     5d/pop-to-ebp
     2449     c3/return
     2450
     2451 test-local-var-in-mem-has-no-initializer:
     2452     # . prologue
     2453     55/push-ebp
     2454     89/<- %ebp 4/r32/esp
     2455     # setup
     2456     (clear-stream _test-input-stream)
     2457     (clear-stream $_test-input-buffered-file->buffer)
     2458     (clear-stream _test-output-stream)
     2459     (clear-stream $_test-output-buffered-file->buffer)
     2460     (clear-stream _test-error-stream)
     2461     (clear-stream $_test-error-buffered-file->buffer)
     2462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2463     68/push 0/imm32
     2464     68/push 0/imm32
     2465     89/<- %edx 4/r32/esp
     2466     (tailor-exit-descriptor %edx 0x10)
     2467     #
     2468     (write _test-input-stream "fn foo {\n")
     2469     (write _test-input-stream "  var x: int <- copy 0\n")
     2470     (write _test-input-stream "  increment x\n")
     2471     (write _test-input-stream "}\n")
     2472     # convert
     2473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2474     # registers except esp clobbered at this point
     2475     # restore ed
     2476     89/<- %edx 4/r32/esp
     2477     (flush _test-output-buffered-file)
     2478     (flush _test-error-buffered-file)
     2479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2485     # check output
     2486     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
     2487     (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")
     2488     # check that stop(1) was called
     2489     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
     2490     # don't restore from ebp
     2491     81 0/subop/add %esp 8/imm32
     2492     # . epilogue
     2493     5d/pop-to-ebp
     2494     c3/return
     2495
     2496 test-convert-function-with-local-var-with-compound-type-in-mem:
     2497     # . prologue
     2498     55/push-ebp
     2499     89/<- %ebp 4/r32/esp
     2500     # setup
     2501     (clear-stream _test-input-stream)
     2502     (clear-stream $_test-input-buffered-file->buffer)
     2503     (clear-stream _test-output-stream)
     2504     (clear-stream $_test-output-buffered-file->buffer)
     2505     #
     2506     (write _test-input-stream "fn foo {\n")
     2507     (write _test-input-stream "  var x: (addr int)\n")
     2508     (write _test-input-stream "  copy-to x, 0\n")
     2509     (write _test-input-stream "}\n")
     2510     # convert
     2511     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2512     (flush _test-output-buffered-file)
     2513 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2519     # check output
     2520     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
     2521     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
     2522     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
     2523     (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")
     2524     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
     2525     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
     2526     (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")
     2527     (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")
     2528     (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")
     2529     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
     2530     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
     2531     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
     2532     (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")
     2533     (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")
     2534     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
     2535     # . epilogue
     2536     89/<- %esp 5/r32/ebp
     2537     5d/pop-to-ebp
     2538     c3/return
     2539
     2540 test-convert-function-with-local-var-in-reg:
     2541     # . prologue
     2542     55/push-ebp
     2543     89/<- %ebp 4/r32/esp
     2544     # setup
     2545     (clear-stream _test-input-stream)
     2546     (clear-stream $_test-input-buffered-file->buffer)
     2547     (clear-stream _test-output-stream)
     2548     (clear-stream $_test-output-buffered-file->buffer)
     2549     #
     2550     (write _test-input-stream "fn foo {\n")
     2551     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2552     (write _test-input-stream "  x <- increment\n")
     2553     (write _test-input-stream "}\n")
     2554     # convert
     2555     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2556     (flush _test-output-buffered-file)
     2557 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2563     # check output
     2564     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
     2565     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
     2566     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
     2567     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
     2568     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
     2569     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
     2570     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
     2571     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
     2572     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
     2573     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
     2574     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
     2575     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
     2576     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
     2577     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
     2578     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
     2579     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
     2580     # . epilogue
     2581     89/<- %esp 5/r32/ebp
     2582     5d/pop-to-ebp
     2583     c3/return
     2584
     2585 test-convert-function-with-local-var-in-same-reg:
     2586     # . prologue
     2587     55/push-ebp
     2588     89/<- %ebp 4/r32/esp
     2589     # setup
     2590     (clear-stream _test-input-stream)
     2591     (clear-stream $_test-input-buffered-file->buffer)
     2592     (clear-stream _test-output-stream)
     2593     (clear-stream $_test-output-buffered-file->buffer)
     2594     #
     2595     (write _test-input-stream "fn foo {\n")
     2596     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2597     (write _test-input-stream "  var y/ecx: int <- copy x\n")
     2598     (write _test-input-stream "}\n")
     2599     # convert
     2600     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2601     (flush _test-output-buffered-file)
     2602 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2608     # check output
     2609     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
     2610     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
     2611     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
     2612     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
     2613     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
     2614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
     2615     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
     2616     (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")
     2617     # optimization: skip the second copy
     2618     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
     2619     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
     2620     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
     2621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
     2622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
     2623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
     2624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
     2625     # . epilogue
     2626     89/<- %esp 5/r32/ebp
     2627     5d/pop-to-ebp
     2628     c3/return
     2629
     2630 test-convert-function-with-local-var-in-same-reg-dereferenced:
     2631     # . prologue
     2632     55/push-ebp
     2633     89/<- %ebp 4/r32/esp
     2634     # setup
     2635     (clear-stream _test-input-stream)
     2636     (clear-stream $_test-input-buffered-file->buffer)
     2637     (clear-stream _test-output-stream)
     2638     (clear-stream $_test-output-buffered-file->buffer)
     2639     #
     2640     (write _test-input-stream "fn foo {\n")
     2641     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
     2642     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
     2643     (write _test-input-stream "}\n")
     2644     # convert
     2645     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2646     (flush _test-output-buffered-file)
     2647 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2653     # check output
     2654     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
     2655     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
     2656     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
     2657     (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")
     2658     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
     2659     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
     2660     (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")
     2661     (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")
     2662     (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
     2663     (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")
     2664     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
     2665     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
     2666     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
     2667     (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")
     2668     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
     2669     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
     2670     # . epilogue
     2671     89/<- %esp 5/r32/ebp
     2672     5d/pop-to-ebp
     2673     c3/return
     2674
     2675 test-float-var-in-wrong-register:
     2676     # . prologue
     2677     55/push-ebp
     2678     89/<- %ebp 4/r32/esp
     2679     # setup
     2680     (clear-stream _test-input-stream)
     2681     (clear-stream $_test-input-buffered-file->buffer)
     2682     (clear-stream _test-output-stream)
     2683     (clear-stream $_test-output-buffered-file->buffer)
     2684     (clear-stream _test-error-stream)
     2685     (clear-stream $_test-error-buffered-file->buffer)
     2686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2687     68/push 0/imm32
     2688     68/push 0/imm32
     2689     89/<- %edx 4/r32/esp
     2690     (tailor-exit-descriptor %edx 0x10)
     2691     #
     2692     (write _test-input-stream "fn foo {\n")
     2693     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     2694     (write _test-input-stream "  var y/eax: float <- convert x\n")
     2695     (write _test-input-stream "}\n")
     2696     # convert
     2697     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2698     # registers except esp clobbered at this point
     2699     # restore ed
     2700     89/<- %edx 4/r32/esp
     2701     (flush _test-output-buffered-file)
     2702     (flush _test-error-buffered-file)
     2703 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2709     # check output
     2710     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
     2711     (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")
     2712     # check that stop(1) was called
     2713     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
     2714     # don't restore from ebp
     2715     81 0/subop/add %esp 8/imm32
     2716     # . epilogue
     2717     5d/pop-to-ebp
     2718     c3/return
     2719
     2720 test-non-float-var-in-wrong-register:
     2721     # . prologue
     2722     55/push-ebp
     2723     89/<- %ebp 4/r32/esp
     2724     # setup
     2725     (clear-stream _test-input-stream)
     2726     (clear-stream $_test-input-buffered-file->buffer)
     2727     (clear-stream _test-output-stream)
     2728     (clear-stream $_test-output-buffered-file->buffer)
     2729     (clear-stream _test-error-stream)
     2730     (clear-stream $_test-error-buffered-file->buffer)
     2731     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2732     68/push 0/imm32
     2733     68/push 0/imm32
     2734     89/<- %edx 4/r32/esp
     2735     (tailor-exit-descriptor %edx 0x10)
     2736     #
     2737     (write _test-input-stream "fn foo {\n")
     2738     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
     2739     (write _test-input-stream "}\n")
     2740     # convert
     2741     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2742     # registers except esp clobbered at this point
     2743     # restore ed
     2744     89/<- %edx 4/r32/esp
     2745     (flush _test-output-buffered-file)
     2746     (flush _test-error-buffered-file)
     2747 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2753     # check output
     2754     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
     2755     (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")
     2756     # check that stop(1) was called
     2757     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
     2758     # don't restore from ebp
     2759     81 0/subop/add %esp 8/imm32
     2760     # . epilogue
     2761     5d/pop-to-ebp
     2762     c3/return
     2763
     2764 test-convert-function-with-allocate:
     2765     # . prologue
     2766     55/push-ebp
     2767     89/<- %ebp 4/r32/esp
     2768     # setup
     2769     (clear-stream _test-input-stream)
     2770     (clear-stream $_test-input-buffered-file->buffer)
     2771     (clear-stream _test-output-stream)
     2772     (clear-stream $_test-output-buffered-file->buffer)
     2773     #
     2774     (write _test-input-stream "fn foo {\n")
     2775     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
     2776     (write _test-input-stream "  allocate x\n")
     2777     (write _test-input-stream "}\n")
     2778     # convert
     2779     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2780     (flush _test-output-buffered-file)
     2781 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2787     # check output
     2788     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
     2789     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
     2790     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
     2791     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
     2792     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
     2793     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
     2794     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
     2795     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
     2796     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
     2797     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
     2798     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
     2799     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
     2800     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
     2801     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
     2802     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
     2803     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
     2804     # . epilogue
     2805     89/<- %esp 5/r32/ebp
     2806     5d/pop-to-ebp
     2807     c3/return
     2808
     2809 test-initializer-in-hex:
     2810     # . prologue
     2811     55/push-ebp
     2812     89/<- %ebp 4/r32/esp
     2813     # setup
     2814     (clear-stream _test-input-stream)
     2815     (clear-stream $_test-input-buffered-file->buffer)
     2816     (clear-stream _test-output-stream)
     2817     (clear-stream $_test-output-buffered-file->buffer)
     2818     (clear-stream _test-error-stream)
     2819     (clear-stream $_test-error-buffered-file->buffer)
     2820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2821     68/push 0/imm32
     2822     68/push 0/imm32
     2823     89/<- %edx 4/r32/esp
     2824     (tailor-exit-descriptor %edx 0x10)
     2825     #
     2826     (write _test-input-stream "fn foo {\n")
     2827     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
     2828     (write _test-input-stream "}\n")
     2829     # convert
     2830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2831     # registers except esp clobbered at this point
     2832     # restore ed
     2833     89/<- %edx 4/r32/esp
     2834     (flush _test-output-buffered-file)
     2835     (flush _test-error-buffered-file)
     2836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2842     # check output
     2843     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
     2844     (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")
     2845     # check that stop(1) was called
     2846     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
     2847     # don't restore from ebp
     2848     81 0/subop/add %esp 8/imm32
     2849     # . epilogue
     2850     5d/pop-to-ebp
     2851     c3/return
     2852
     2853 test-convert-function-with-second-local-var-in-same-reg:
     2854     # . prologue
     2855     55/push-ebp
     2856     89/<- %ebp 4/r32/esp
     2857     # setup
     2858     (clear-stream _test-input-stream)
     2859     (clear-stream $_test-input-buffered-file->buffer)
     2860     (clear-stream _test-output-stream)
     2861     (clear-stream $_test-output-buffered-file->buffer)
     2862     #
     2863     (write _test-input-stream "fn foo {\n")
     2864     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2865     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     2866     (write _test-input-stream "  y <- increment\n")
     2867     (write _test-input-stream "}\n")
     2868     # convert
     2869     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2870     (flush _test-output-buffered-file)
     2871 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2877     # check output
     2878     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
     2879     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
     2880     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
     2881     (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")
     2882     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
     2883     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
     2884     (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")
     2885     (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")
     2886     (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")
     2887     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
     2888     (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")
     2889     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
     2890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
     2891     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
     2892     (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")
     2893     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
     2894     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
     2895     # . epilogue
     2896     89/<- %esp 5/r32/ebp
     2897     5d/pop-to-ebp
     2898     c3/return
     2899
     2900 test-read-clobbered-reg-var:
     2901     # . prologue
     2902     55/push-ebp
     2903     89/<- %ebp 4/r32/esp
     2904     # setup
     2905     (clear-stream _test-input-stream)
     2906     (clear-stream $_test-input-buffered-file->buffer)
     2907     (clear-stream _test-output-stream)
     2908     (clear-stream $_test-output-buffered-file->buffer)
     2909     (clear-stream _test-error-stream)
     2910     (clear-stream $_test-error-buffered-file->buffer)
     2911     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     2912     68/push 0/imm32
     2913     68/push 0/imm32
     2914     89/<- %edx 4/r32/esp
     2915     (tailor-exit-descriptor %edx 0x10)
     2916     #
     2917     (write _test-input-stream "fn foo {\n")
     2918     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2919     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     2920     (write _test-input-stream "  x <- increment\n")
     2921     (write _test-input-stream "}\n")
     2922     # convert
     2923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2924     # registers except esp clobbered at this point
     2925     # restore ed
     2926     89/<- %edx 4/r32/esp
     2927     (flush _test-output-buffered-file)
     2928     (flush _test-error-buffered-file)
     2929 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2935     # check output
     2936     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
     2937     (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")
     2938     # check that stop(1) was called
     2939     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
     2940     # don't restore from ebp
     2941     81 0/subop/add %esp 8/imm32
     2942     # . epilogue
     2943     5d/pop-to-ebp
     2944     c3/return
     2945
     2946 test-overlapping-int-fp-registers:
     2947     # . prologue
     2948     55/push-ebp
     2949     89/<- %ebp 4/r32/esp
     2950     # setup
     2951     (clear-stream _test-input-stream)
     2952     (clear-stream $_test-input-buffered-file->buffer)
     2953     (clear-stream _test-output-stream)
     2954     (clear-stream $_test-output-buffered-file->buffer)
     2955     (clear-stream _test-error-stream)
     2956     (clear-stream $_test-error-buffered-file->buffer)
     2957     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     2958     68/push 0/imm32
     2959     68/push 0/imm32
     2960     89/<- %edx 4/r32/esp
     2961     (tailor-exit-descriptor %edx 0x10)
     2962     #
     2963     (write _test-input-stream "fn foo {\n")
     2964     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     2965     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
     2966     (write _test-input-stream "  x <- increment\n")
     2967     (write _test-input-stream "}\n")
     2968     # convert
     2969     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2970     # registers except esp clobbered at this point
     2971     # restore ed
     2972     89/<- %edx 4/r32/esp
     2973     (flush _test-output-buffered-file)
     2974     (flush _test-error-buffered-file)
     2975 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2981     # no errors
     2982     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
     2983     # don't bother checking the generated code
     2984     # don't restore from ebp
     2985     81 0/subop/add %esp 8/imm32
     2986     # . epilogue
     2987     5d/pop-to-ebp
     2988     c3/return
     2989
     2990 test-convert-function-call:
     2991     # . prologue
     2992     55/push-ebp
     2993     89/<- %ebp 4/r32/esp
     2994     # setup
     2995     (clear-stream _test-input-stream)
     2996     (clear-stream $_test-input-buffered-file->buffer)
     2997     (clear-stream _test-output-stream)
     2998     (clear-stream $_test-output-buffered-file->buffer)
     2999     #
     3000     (write _test-input-stream "fn main -> _/ebx: int {\n")
     3001     (write _test-input-stream "  var result/ebx: int <- foo\n")
     3002     (write _test-input-stream "  return result\n")
     3003     (write _test-input-stream "}\n")
     3004     (write _test-input-stream "fn foo -> _/ebx: int {\n")
     3005     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
     3006     (write _test-input-stream "  return result\n")
     3007     (write _test-input-stream "}\n")
     3008     # convert
     3009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3010     (flush _test-output-buffered-file)
     3011 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3017     # check output
     3018     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
     3019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
     3020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
     3021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
     3022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
     3023     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
     3024     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
     3025     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
     3026     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     3027     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     3028     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     3029     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
     3030     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
     3031     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
     3032     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
     3033     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
     3034     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
     3035     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
     3036     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
     3037     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
     3038     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
     3039     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
     3040     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
     3041     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
     3042     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
     3043     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     3044     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     3045     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     3046     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
     3047     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
     3048     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
     3049     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
     3050     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
     3051     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
     3052     # . epilogue
     3053     89/<- %esp 5/r32/ebp
     3054     5d/pop-to-ebp
     3055     c3/return
     3056
     3057 test-convert-function-call-with-inout-with-compound-type:
     3058     # . prologue
     3059     55/push-ebp
     3060     89/<- %ebp 4/r32/esp
     3061     # setup
     3062     (clear-stream _test-input-stream)
     3063     (clear-stream $_test-input-buffered-file->buffer)
     3064     (clear-stream _test-output-stream)
     3065     (clear-stream $_test-output-buffered-file->buffer)
     3066     #
     3067     (write _test-input-stream "fn f {\n")
     3068     (write _test-input-stream "  var x: (addr int)\n")
     3069     (write _test-input-stream "  g x\n")
     3070     (write _test-input-stream "}\n")
     3071     (write _test-input-stream "fn g a: (addr int) {\n")
     3072     (write _test-input-stream "}\n")
     3073     # convert
     3074     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3075     (flush _test-output-buffered-file)
     3076 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3082     # check output
     3083     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
     3084     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
     3085     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
     3086     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
     3087     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
     3088     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
     3089     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
     3090     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
     3091     (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")
     3092     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
     3093     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
     3094     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
     3095     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
     3096     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
     3097     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
     3098     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
     3099     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
     3100     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
     3101     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
     3102     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
     3103     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
     3104     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
     3105     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
     3106     # . epilogue
     3107     89/<- %esp 5/r32/ebp
     3108     5d/pop-to-ebp
     3109     c3/return
     3110
     3111 test-convert-function-call-with-inout-with-type-parameter:
     3112     # . prologue
     3113     55/push-ebp
     3114     89/<- %ebp 4/r32/esp
     3115     # setup
     3116     (clear-stream _test-input-stream)
     3117     (clear-stream $_test-input-buffered-file->buffer)
     3118     (clear-stream _test-output-stream)
     3119     (clear-stream $_test-output-buffered-file->buffer)
     3120     (clear-stream _test-error-stream)
     3121     (clear-stream $_test-error-buffered-file->buffer)
     3122     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3123     68/push 0/imm32
     3124     68/push 0/imm32
     3125     89/<- %edx 4/r32/esp
     3126     (tailor-exit-descriptor %edx 0x10)
     3127     #
     3128     (write _test-input-stream "fn f {\n")
     3129     (write _test-input-stream "  var x: (addr int)\n")
     3130     (write _test-input-stream "  g x\n")
     3131     (write _test-input-stream "}\n")
     3132     (write _test-input-stream "fn g a: (addr _) {\n")
     3133     (write _test-input-stream "}\n")
     3134     # convert
     3135     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3136     # registers except esp clobbered at this point
     3137     # restore ed
     3138     89/<- %edx 4/r32/esp
     3139     (flush _test-output-buffered-file)
     3140     (flush _test-error-buffered-file)
     3141 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3147     # no error; types matched
     3148     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
     3149     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
     3150     # don't restore from ebp
     3151     81 0/subop/add %esp 8/imm32
     3152     # . epilogue
     3153     5d/pop-to-ebp
     3154     c3/return
     3155
     3156 test-convert-function-call-with-incorrect-inout-type:
     3157     # . prologue
     3158     55/push-ebp
     3159     89/<- %ebp 4/r32/esp
     3160     # setup
     3161     (clear-stream _test-input-stream)
     3162     (clear-stream $_test-input-buffered-file->buffer)
     3163     (clear-stream _test-output-stream)
     3164     (clear-stream $_test-output-buffered-file->buffer)
     3165     (clear-stream _test-error-stream)
     3166     (clear-stream $_test-error-buffered-file->buffer)
     3167     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3168     68/push 0/imm32
     3169     68/push 0/imm32
     3170     89/<- %edx 4/r32/esp
     3171     (tailor-exit-descriptor %edx 0x10)
     3172     #
     3173     (write _test-input-stream "fn f {\n")
     3174     (write _test-input-stream "  var x: int\n")
     3175     (write _test-input-stream "  g x\n")
     3176     (write _test-input-stream "}\n")
     3177     (write _test-input-stream "fn g a: foo {\n")
     3178     (write _test-input-stream "}\n")
     3179     # convert
     3180     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3181     # registers except esp clobbered at this point
     3182     # restore ed
     3183     89/<- %edx 4/r32/esp
     3184     (flush _test-output-buffered-file)
     3185     (flush _test-error-buffered-file)
     3186 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3192     # check output
     3193     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
     3194     (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")
     3195     # check that stop(1) was called
     3196     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
     3197     # don't restore from ebp
     3198     81 0/subop/add %esp 8/imm32
     3199     5d/pop-to-ebp
     3200     c3/return
     3201
     3202 test-convert-function-call-with-inout-with-incorrect-compound-type:
     3203     # . prologue
     3204     55/push-ebp
     3205     89/<- %ebp 4/r32/esp
     3206     # setup
     3207     (clear-stream _test-input-stream)
     3208     (clear-stream $_test-input-buffered-file->buffer)
     3209     (clear-stream _test-output-stream)
     3210     (clear-stream $_test-output-buffered-file->buffer)
     3211     (clear-stream _test-error-stream)
     3212     (clear-stream $_test-error-buffered-file->buffer)
     3213     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3214     68/push 0/imm32
     3215     68/push 0/imm32
     3216     89/<- %edx 4/r32/esp
     3217     (tailor-exit-descriptor %edx 0x10)
     3218     #
     3219     (write _test-input-stream "fn f {\n")
     3220     (write _test-input-stream "  var x: (addr int)\n")
     3221     (write _test-input-stream "  g x\n")
     3222     (write _test-input-stream "}\n")
     3223     (write _test-input-stream "fn g a: (addr bool) {\n")
     3224     (write _test-input-stream "}\n")
     3225     # convert
     3226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3227     # registers except esp clobbered at this point
     3228     # restore ed
     3229     89/<- %edx 4/r32/esp
     3230     (flush _test-output-buffered-file)
     3231     (flush _test-error-buffered-file)
     3232 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3238     # check output
     3239     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
     3240     (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")
     3241     # don't restore from ebp
     3242     81 0/subop/add %esp 8/imm32
     3243     # . epilogue
     3244     5d/pop-to-ebp
     3245     c3/return
     3246
     3247 test-convert-function-call-with-inout-with-multiple-type-parameters:
     3248     # . prologue
     3249     55/push-ebp
     3250     89/<- %ebp 4/r32/esp
     3251     # setup
     3252     (clear-stream _test-input-stream)
     3253     (clear-stream $_test-input-buffered-file->buffer)
     3254     (clear-stream _test-output-stream)
     3255     (clear-stream $_test-output-buffered-file->buffer)
     3256     (clear-stream _test-error-stream)
     3257     (clear-stream $_test-error-buffered-file->buffer)
     3258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3259     68/push 0/imm32
     3260     68/push 0/imm32
     3261     89/<- %edx 4/r32/esp
     3262     (tailor-exit-descriptor %edx 0x10)
     3263     #
     3264     (write _test-input-stream "fn f {\n")
     3265     (write _test-input-stream "  var x: (addr int)\n")
     3266     (write _test-input-stream "  var y: (addr int)\n")
     3267     (write _test-input-stream "  g x, y\n")
     3268     (write _test-input-stream "}\n")
     3269     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
     3270     (write _test-input-stream "}\n")
     3271     # convert
     3272     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3273     # registers except esp clobbered at this point
     3274     # restore ed
     3275     89/<- %edx 4/r32/esp
     3276     (flush _test-output-buffered-file)
     3277     (flush _test-error-buffered-file)
     3278 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3284     # no errors
     3285     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
     3286     # don't bother checking the generated code
     3287     # don't restore from ebp
     3288     81 0/subop/add %esp 8/imm32
     3289     # . epilogue
     3290     5d/pop-to-ebp
     3291     c3/return
     3292
     3293 test-type-parameter-matches-rest-of-type:
     3294     # . prologue
     3295     55/push-ebp
     3296     89/<- %ebp 4/r32/esp
     3297     # setup
     3298     (clear-stream _test-input-stream)
     3299     (clear-stream $_test-input-buffered-file->buffer)
     3300     (clear-stream _test-output-stream)
     3301     (clear-stream $_test-output-buffered-file->buffer)
     3302     (clear-stream _test-error-stream)
     3303     (clear-stream $_test-error-buffered-file->buffer)
     3304     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3305     68/push 0/imm32
     3306     68/push 0/imm32
     3307     89/<- %edx 4/r32/esp
     3308     (tailor-exit-descriptor %edx 0x10)
     3309     #
     3310     (write _test-input-stream "fn f {\n")
     3311     (write _test-input-stream "  var x: (addr array int)\n")
     3312     (write _test-input-stream "  g x\n")
     3313     (write _test-input-stream "}\n")
     3314     (write _test-input-stream "fn g a: (addr _) {\n")
     3315     (write _test-input-stream "}\n")
     3316     # convert
     3317     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3318     # registers except esp clobbered at this point
     3319     # restore ed
     3320     89/<- %edx 4/r32/esp
     3321     (flush _test-output-buffered-file)
     3322     (flush _test-error-buffered-file)
     3323 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3329     # no errors
     3330     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
     3331     # don't bother checking the generated code
     3332     # don't restore from ebp
     3333     81 0/subop/add %esp 8/imm32
     3334     # . epilogue
     3335     5d/pop-to-ebp
     3336     c3/return
     3337
     3338 test-convert-function-call-with-inout-with-incompatible-type-parameters:
     3339     # . prologue
     3340     55/push-ebp
     3341     89/<- %ebp 4/r32/esp
     3342     # setup
     3343     (clear-stream _test-input-stream)
     3344     (clear-stream $_test-input-buffered-file->buffer)
     3345     (clear-stream _test-output-stream)
     3346     (clear-stream $_test-output-buffered-file->buffer)
     3347     (clear-stream _test-error-stream)
     3348     (clear-stream $_test-error-buffered-file->buffer)
     3349     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3350     68/push 0/imm32
     3351     68/push 0/imm32
     3352     89/<- %edx 4/r32/esp
     3353     (tailor-exit-descriptor %edx 0x10)
     3354     #
     3355     (write _test-input-stream "fn f {\n")
     3356     (write _test-input-stream "  var x: (addr int)\n")
     3357     (write _test-input-stream "  var y: (addr boolean)\n")
     3358     (write _test-input-stream "  g x, y\n")
     3359     (write _test-input-stream "}\n")
     3360     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
     3361     (write _test-input-stream "}\n")
     3362     # convert
     3363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3364     # registers except esp clobbered at this point
     3365     # restore ed
     3366     89/<- %edx 4/r32/esp
     3367     (flush _test-output-buffered-file)
     3368     (flush _test-error-buffered-file)
     3369 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3375     # check output
     3376     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
     3377     (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")
     3378     # don't restore from ebp
     3379     81 0/subop/add %esp 8/imm32
     3380     # . epilogue
     3381     5d/pop-to-ebp
     3382     c3/return
     3383
     3384 test-convert-function-call-with-too-few-inouts:
     3385     # . prologue
     3386     55/push-ebp
     3387     89/<- %ebp 4/r32/esp
     3388     # setup
     3389     (clear-stream _test-input-stream)
     3390     (clear-stream $_test-input-buffered-file->buffer)
     3391     (clear-stream _test-output-stream)
     3392     (clear-stream $_test-output-buffered-file->buffer)
     3393     (clear-stream _test-error-stream)
     3394     (clear-stream $_test-error-buffered-file->buffer)
     3395     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3396     68/push 0/imm32
     3397     68/push 0/imm32
     3398     89/<- %edx 4/r32/esp
     3399     (tailor-exit-descriptor %edx 0x10)
     3400     #
     3401     (write _test-input-stream "fn f {\n")
     3402     (write _test-input-stream "  g\n")
     3403     (write _test-input-stream "}\n")
     3404     (write _test-input-stream "fn g a: int {\n")
     3405     (write _test-input-stream "}\n")
     3406     # convert
     3407     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3408     # registers except esp clobbered at this point
     3409     # restore ed
     3410     89/<- %edx 4/r32/esp
     3411     (flush _test-output-buffered-file)
     3412     (flush _test-error-buffered-file)
     3413 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3419     # check output
     3420     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
     3421     (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")
     3422     # check that stop(1) was called
     3423     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
     3424     # don't restore from ebp
     3425     81 0/subop/add %esp 8/imm32
     3426     5d/pop-to-ebp
     3427     c3/return
     3428
     3429 test-convert-function-call-with-too-many-inouts:
     3430     # . prologue
     3431     55/push-ebp
     3432     89/<- %ebp 4/r32/esp
     3433     # setup
     3434     (clear-stream _test-input-stream)
     3435     (clear-stream $_test-input-buffered-file->buffer)
     3436     (clear-stream _test-output-stream)
     3437     (clear-stream $_test-output-buffered-file->buffer)
     3438     (clear-stream _test-error-stream)
     3439     (clear-stream $_test-error-buffered-file->buffer)
     3440     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3441     68/push 0/imm32
     3442     68/push 0/imm32
     3443     89/<- %edx 4/r32/esp
     3444     (tailor-exit-descriptor %edx 0x10)
     3445     #
     3446     (write _test-input-stream "fn f {\n")
     3447     (write _test-input-stream "  var x: int\n")
     3448     (write _test-input-stream "  g x\n")
     3449     (write _test-input-stream "}\n")
     3450     (write _test-input-stream "fn g {\n")
     3451     (write _test-input-stream "}\n")
     3452     # convert
     3453     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3454     # registers except esp clobbered at this point
     3455     # restore ed
     3456     89/<- %edx 4/r32/esp
     3457     (flush _test-output-buffered-file)
     3458     (flush _test-error-buffered-file)
     3459 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3465     # check output
     3466     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
     3467     (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")
     3468     # check that stop(1) was called
     3469     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
     3470     # don't restore from ebp
     3471     81 0/subop/add %esp 8/imm32
     3472     5d/pop-to-ebp
     3473     c3/return
     3474
     3475 test-convert-function-call-with-incorrect-output-type:
     3476     # . prologue
     3477     55/push-ebp
     3478     89/<- %ebp 4/r32/esp
     3479     # setup
     3480     (clear-stream _test-input-stream)
     3481     (clear-stream $_test-input-buffered-file->buffer)
     3482     (clear-stream _test-output-stream)
     3483     (clear-stream $_test-output-buffered-file->buffer)
     3484     (clear-stream _test-error-stream)
     3485     (clear-stream $_test-error-buffered-file->buffer)
     3486     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3487     68/push 0/imm32
     3488     68/push 0/imm32
     3489     89/<- %edx 4/r32/esp
     3490     (tailor-exit-descriptor %edx 0x10)
     3491     #
     3492     (write _test-input-stream "fn f {\n")
     3493     (write _test-input-stream "  var x/eax: int <- g\n")
     3494     (write _test-input-stream "}\n")
     3495     (write _test-input-stream "fn g -> _/eax: foo {\n")
     3496     (write _test-input-stream "}\n")
     3497     # convert
     3498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3499     # registers except esp clobbered at this point
     3500     # restore ed
     3501     89/<- %edx 4/r32/esp
     3502     (flush _test-output-buffered-file)
     3503     (flush _test-error-buffered-file)
     3504 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3510     # check output
     3511     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
     3512     (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")
     3513     # check that stop(1) was called
     3514     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
     3515     # don't restore from ebp
     3516     81 0/subop/add %esp 8/imm32
     3517     5d/pop-to-ebp
     3518     c3/return
     3519
     3520 test-convert-function-call-with-too-few-outputs:
     3521     # . prologue
     3522     55/push-ebp
     3523     89/<- %ebp 4/r32/esp
     3524     # setup
     3525     (clear-stream _test-input-stream)
     3526     (clear-stream $_test-input-buffered-file->buffer)
     3527     (clear-stream _test-output-stream)
     3528     (clear-stream $_test-output-buffered-file->buffer)
     3529     (clear-stream _test-error-stream)
     3530     (clear-stream $_test-error-buffered-file->buffer)
     3531     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3532     68/push 0/imm32
     3533     68/push 0/imm32
     3534     89/<- %edx 4/r32/esp
     3535     (tailor-exit-descriptor %edx 0x10)
     3536     #
     3537     (write _test-input-stream "fn f {\n")
     3538     (write _test-input-stream "  g\n")
     3539     (write _test-input-stream "}\n")
     3540     (write _test-input-stream "fn g -> _/eax: int {\n")
     3541     (write _test-input-stream "}\n")
     3542     # convert
     3543     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3544     # registers except esp clobbered at this point
     3545     # restore ed
     3546     89/<- %edx 4/r32/esp
     3547     (flush _test-output-buffered-file)
     3548     (flush _test-error-buffered-file)
     3549 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3555     # check output
     3556     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
     3557     (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")
     3558     # check that stop(1) was called
     3559     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
     3560     # don't restore from ebp
     3561     81 0/subop/add %esp 8/imm32
     3562     5d/pop-to-ebp
     3563     c3/return
     3564
     3565 test-convert-function-call-with-too-many-outputs:
     3566     # . prologue
     3567     55/push-ebp
     3568     89/<- %ebp 4/r32/esp
     3569     # setup
     3570     (clear-stream _test-input-stream)
     3571     (clear-stream $_test-input-buffered-file->buffer)
     3572     (clear-stream _test-output-stream)
     3573     (clear-stream $_test-output-buffered-file->buffer)
     3574     (clear-stream _test-error-stream)
     3575     (clear-stream $_test-error-buffered-file->buffer)
     3576     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3577     68/push 0/imm32
     3578     68/push 0/imm32
     3579     89/<- %edx 4/r32/esp
     3580     (tailor-exit-descriptor %edx 0x10)
     3581     #
     3582     (write _test-input-stream "fn f {\n")
     3583     (write _test-input-stream "  var x/eax: int <- g\n")
     3584     (write _test-input-stream "}\n")
     3585     (write _test-input-stream "fn g {\n")
     3586     (write _test-input-stream "}\n")
     3587     # convert
     3588     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3589     # registers except esp clobbered at this point
     3590     # restore ed
     3591     89/<- %edx 4/r32/esp
     3592     (flush _test-output-buffered-file)
     3593     (flush _test-error-buffered-file)
     3594 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3600     # check output
     3601     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
     3602     (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")
     3603     # check that stop(1) was called
     3604     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
     3605     # don't restore from ebp
     3606     81 0/subop/add %esp 8/imm32
     3607     5d/pop-to-ebp
     3608     c3/return
     3609
     3610 test-convert-function-call-with-missing-output-register:
     3611     # . prologue
     3612     55/push-ebp
     3613     89/<- %ebp 4/r32/esp
     3614     # setup
     3615     (clear-stream _test-input-stream)
     3616     (clear-stream $_test-input-buffered-file->buffer)
     3617     (clear-stream _test-output-stream)
     3618     (clear-stream $_test-output-buffered-file->buffer)
     3619     (clear-stream _test-error-stream)
     3620     (clear-stream $_test-error-buffered-file->buffer)
     3621     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3622     68/push 0/imm32
     3623     68/push 0/imm32
     3624     89/<- %edx 4/r32/esp
     3625     (tailor-exit-descriptor %edx 0x10)
     3626     #
     3627     (write _test-input-stream "fn f {\n")
     3628     (write _test-input-stream "  var x: int\n")
     3629     (write _test-input-stream "  x <- g\n")
     3630     (write _test-input-stream "}\n")
     3631     (write _test-input-stream "fn g -> _/eax: int {\n")
     3632     (write _test-input-stream "}\n")
     3633     # convert
     3634     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3635     # registers except esp clobbered at this point
     3636     # restore ed
     3637     89/<- %edx 4/r32/esp
     3638     (flush _test-output-buffered-file)
     3639     (flush _test-error-buffered-file)
     3640 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3646     # check output
     3647     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
     3648     (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")
     3649     # check that stop(1) was called
     3650     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
     3651     # don't restore from ebp
     3652     81 0/subop/add %esp 8/imm32
     3653     5d/pop-to-ebp
     3654     c3/return
     3655
     3656 test-convert-function-call-with-incorrect-output-register:
     3657     # . prologue
     3658     55/push-ebp
     3659     89/<- %ebp 4/r32/esp
     3660     # setup
     3661     (clear-stream _test-input-stream)
     3662     (clear-stream $_test-input-buffered-file->buffer)
     3663     (clear-stream _test-output-stream)
     3664     (clear-stream $_test-output-buffered-file->buffer)
     3665     (clear-stream _test-error-stream)
     3666     (clear-stream $_test-error-buffered-file->buffer)
     3667     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3668     68/push 0/imm32
     3669     68/push 0/imm32
     3670     89/<- %edx 4/r32/esp
     3671     (tailor-exit-descriptor %edx 0x10)
     3672     #
     3673     (write _test-input-stream "fn f {\n")
     3674     (write _test-input-stream "  var x/ecx: int <- g\n")
     3675     (write _test-input-stream "}\n")
     3676     (write _test-input-stream "fn g -> _/eax: int {\n")
     3677     (write _test-input-stream "}\n")
     3678     # convert
     3679     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3680     # registers except esp clobbered at this point
     3681     # restore ed
     3682     89/<- %edx 4/r32/esp
     3683     (flush _test-output-buffered-file)
     3684     (flush _test-error-buffered-file)
     3685 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3691     # check output
     3692     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
     3693     (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")
     3694     # check that stop(1) was called
     3695     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
     3696     # don't restore from ebp
     3697     81 0/subop/add %esp 8/imm32
     3698     5d/pop-to-ebp
     3699     c3/return
     3700
     3701 test-convert-function-with-local-var-dereferenced:
     3702     # . prologue
     3703     55/push-ebp
     3704     89/<- %ebp 4/r32/esp
     3705     # setup
     3706     (clear-stream _test-input-stream)
     3707     (clear-stream $_test-input-buffered-file->buffer)
     3708     (clear-stream _test-output-stream)
     3709     (clear-stream $_test-output-buffered-file->buffer)
     3710     #
     3711     (write _test-input-stream "fn foo {\n")
     3712     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
     3713     (write _test-input-stream "  increment *x\n")
     3714     (write _test-input-stream "}\n")
     3715     # convert
     3716     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3717     (flush _test-output-buffered-file)
     3718 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3724     # check output
     3725     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
     3726     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
     3727     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
     3728     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
     3729     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
     3730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
     3731     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
     3732     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
     3733     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
     3734     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
     3735     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
     3736     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
     3737     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
     3738     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
     3739     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
     3740     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
     3741     # . epilogue
     3742     89/<- %esp 5/r32/ebp
     3743     5d/pop-to-ebp
     3744     c3/return
     3745
     3746 test-dereference-of-var-on-stack:
     3747     # . prologue
     3748     55/push-ebp
     3749     89/<- %ebp 4/r32/esp
     3750     # setup
     3751     (clear-stream _test-input-stream)
     3752     (clear-stream $_test-input-buffered-file->buffer)
     3753     (clear-stream _test-output-stream)
     3754     (clear-stream $_test-output-buffered-file->buffer)
     3755     (clear-stream _test-error-stream)
     3756     (clear-stream $_test-error-buffered-file->buffer)
     3757     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3758     68/push 0/imm32
     3759     68/push 0/imm32
     3760     89/<- %edx 4/r32/esp
     3761     (tailor-exit-descriptor %edx 0x10)
     3762     #
     3763     (write _test-input-stream "fn foo {\n")
     3764     (write _test-input-stream "  var x: (addr int)\n")
     3765     (write _test-input-stream "  increment *x\n")
     3766     (write _test-input-stream "}\n")
     3767     # convert
     3768     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3769     # registers except esp clobbered at this point
     3770     # restore ed
     3771     89/<- %edx 4/r32/esp
     3772     (flush _test-output-buffered-file)
     3773     (flush _test-error-buffered-file)
     3774 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3780     # check output
     3781     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
     3782     (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")
     3783     # check that stop(1) was called
     3784     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
     3785     # don't restore from ebp
     3786     81 0/subop/add %esp 8/imm32
     3787     # . epilogue
     3788     5d/pop-to-ebp
     3789     c3/return
     3790
     3791 test-convert-function-with-byte-operations:
     3792     # . prologue
     3793     55/push-ebp
     3794     89/<- %ebp 4/r32/esp
     3795     # setup
     3796     (clear-stream _test-input-stream)
     3797     (clear-stream $_test-input-buffered-file->buffer)
     3798     (clear-stream _test-output-stream)
     3799     (clear-stream $_test-output-buffered-file->buffer)
     3800     #
     3801     (write _test-input-stream "fn foo {\n")
     3802     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     3803     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     3804     (write _test-input-stream "  y <- copy-byte x\n")
     3805     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
     3806     (write _test-input-stream "  y <- copy-byte *z\n")
     3807     (write _test-input-stream "  copy-byte-to *z, x\n")
     3808     (write _test-input-stream "}\n")
     3809     # convert
     3810     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3811     (flush _test-output-buffered-file)
     3812 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3818     # check output
     3819     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
     3820     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
     3821     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
     3822     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
     3823     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
     3824     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
     3825     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
     3826     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
     3827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
     3828     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
     3829     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
     3830     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
     3831     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
     3832     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
     3833     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
     3834     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
     3835     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
     3836     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
     3837     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
     3838     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
     3839     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
     3840     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
     3841     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
     3842     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
     3843     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
     3844     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
     3845     # . epilogue
     3846     89/<- %esp 5/r32/ebp
     3847     5d/pop-to-ebp
     3848     c3/return
     3849
     3850 # variables of type 'byte' are not allowed on the stack
     3851 test-byte-values-on-stack:
     3852     # . prologue
     3853     55/push-ebp
     3854     89/<- %ebp 4/r32/esp
     3855     # setup
     3856     (clear-stream _test-input-stream)
     3857     (clear-stream $_test-input-buffered-file->buffer)
     3858     (clear-stream _test-output-stream)
     3859     (clear-stream $_test-output-buffered-file->buffer)
     3860     (clear-stream _test-error-stream)
     3861     (clear-stream $_test-error-buffered-file->buffer)
     3862     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3863     68/push 0/imm32
     3864     68/push 0/imm32
     3865     89/<- %edx 4/r32/esp
     3866     (tailor-exit-descriptor %edx 0x10)
     3867     #
     3868     (write _test-input-stream "fn foo {\n")
     3869     (write _test-input-stream "  var x: byte\n")
     3870     (write _test-input-stream "}\n")
     3871     # convert
     3872     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3873     # registers except esp clobbered at this point
     3874     # restore ed
     3875     89/<- %edx 4/r32/esp
     3876     (flush _test-output-buffered-file)
     3877     (flush _test-error-buffered-file)
     3878 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3884     # check output
     3885     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
     3886     (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")
     3887     # check that stop(1) was called
     3888     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
     3889     # don't restore from ebp
     3890     81 0/subop/add %esp 8/imm32
     3891     # . epilogue
     3892     5d/pop-to-ebp
     3893     c3/return
     3894
     3895 # variables of type 'byte' are not allowed in esi or edi
     3896 test-byte-values-in-unsupported-registers:
     3897     # . prologue
     3898     55/push-ebp
     3899     89/<- %ebp 4/r32/esp
     3900     # setup
     3901     (clear-stream _test-input-stream)
     3902     (clear-stream $_test-input-buffered-file->buffer)
     3903     (clear-stream _test-output-stream)
     3904     (clear-stream $_test-output-buffered-file->buffer)
     3905     (clear-stream _test-error-stream)
     3906     (clear-stream $_test-error-buffered-file->buffer)
     3907     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3908     68/push 0/imm32
     3909     68/push 0/imm32
     3910     89/<- %edx 4/r32/esp
     3911     (tailor-exit-descriptor %edx 0x10)
     3912     #
     3913     (write _test-input-stream "fn foo {\n")
     3914     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
     3915     (write _test-input-stream "}\n")
     3916     # convert
     3917     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3918     # registers except esp clobbered at this point
     3919     # restore ed
     3920     89/<- %edx 4/r32/esp
     3921     (flush _test-output-buffered-file)
     3922     (flush _test-error-buffered-file)
     3923 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3929     # check output
     3930     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
     3931     (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")
     3932     # check that stop(1) was called
     3933     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
     3934     # don't restore from ebp
     3935     81 0/subop/add %esp 8/imm32
     3936     # . epilogue
     3937     5d/pop-to-ebp
     3938     c3/return
     3939
     3940 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
     3941 test-copy-byte-var-from-fn-arg:
     3942     # . prologue
     3943     55/push-ebp
     3944     89/<- %ebp 4/r32/esp
     3945     # setup
     3946     (clear-stream _test-input-stream)
     3947     (clear-stream $_test-input-buffered-file->buffer)
     3948     (clear-stream _test-output-stream)
     3949     (clear-stream $_test-output-buffered-file->buffer)
     3950     #
     3951     (write _test-input-stream "fn foo x: byte, y: int {\n")
     3952     (write _test-input-stream "  var a/eax: byte <- copy x\n")
     3953     (write _test-input-stream "  var b/eax: int <- copy y\n")
     3954     (write _test-input-stream "}\n")
     3955     # convert
     3956     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3957     (flush _test-output-buffered-file)
     3958 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3964     # check output
     3965     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
     3966     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
     3967     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
     3968     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
     3969     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
     3970     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
     3971     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
     3972     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
     3973     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
     3974     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
     3975     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
     3976     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
     3977     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
     3978     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
     3979     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
     3980     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
     3981     # . epilogue
     3982     89/<- %esp 5/r32/ebp
     3983     5d/pop-to-ebp
     3984     c3/return
     3985
     3986 test-convert-compare-register-with-literal:
     3987     # . prologue
     3988     55/push-ebp
     3989     89/<- %ebp 4/r32/esp
     3990     # setup
     3991     (clear-stream _test-input-stream)
     3992     (clear-stream $_test-input-buffered-file->buffer)
     3993     (clear-stream _test-output-stream)
     3994     (clear-stream $_test-output-buffered-file->buffer)
     3995     #
     3996     (write _test-input-stream "fn foo {\n")
     3997     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
     3998     (write _test-input-stream "  compare x, 0\n")
     3999     (write _test-input-stream "}\n")
     4000     # convert
     4001     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4002     (flush _test-output-buffered-file)
     4003 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4009     # check output
     4010     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
     4011     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
     4012     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
     4013     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
     4014     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
     4015     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
     4016     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
     4017     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
     4018     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
     4019     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
     4020     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
     4021     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
     4022     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
     4023     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
     4024     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
     4025     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
     4026     # . epilogue
     4027     89/<- %esp 5/r32/ebp
     4028     5d/pop-to-ebp
     4029     c3/return
     4030
     4031 test-convert-compare-byte-with-literal:
     4032     # . prologue
     4033     55/push-ebp
     4034     89/<- %ebp 4/r32/esp
     4035     # setup
     4036     (clear-stream _test-input-stream)
     4037     (clear-stream $_test-input-buffered-file->buffer)
     4038     (clear-stream _test-output-stream)
     4039     (clear-stream $_test-output-buffered-file->buffer)
     4040     #
     4041     (write _test-input-stream "fn foo {\n")
     4042     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
     4043     (write _test-input-stream "  compare x, 0\n")
     4044     (write _test-input-stream "}\n")
     4045     # convert
     4046     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4047     (flush _test-output-buffered-file)
     4048 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4054     # no errors; output is identical to test-convert-compare-register-with-literal
     4055     # . epilogue
     4056     89/<- %esp 5/r32/ebp
     4057     5d/pop-to-ebp
     4058     c3/return
     4059
     4060 test-unknown-variable:
     4061     # . prologue
     4062     55/push-ebp
     4063     89/<- %ebp 4/r32/esp
     4064     # setup
     4065     (clear-stream _test-input-stream)
     4066     (clear-stream $_test-input-buffered-file->buffer)
     4067     (clear-stream _test-output-stream)
     4068     (clear-stream $_test-output-buffered-file->buffer)
     4069     (clear-stream _test-error-stream)
     4070     (clear-stream $_test-error-buffered-file->buffer)
     4071     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     4072     68/push 0/imm32
     4073     68/push 0/imm32
     4074     89/<- %edx 4/r32/esp
     4075     (tailor-exit-descriptor %edx 0x10)
     4076     #
     4077     (write _test-input-stream "fn foo {\n")
     4078     (write _test-input-stream "  compare x, 0\n")
     4079     (write _test-input-stream "}\n")
     4080     # convert
     4081     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     4082     # registers except esp clobbered at this point
     4083     # restore ed
     4084     89/<- %edx 4/r32/esp
     4085     (flush _test-output-buffered-file)
     4086     (flush _test-error-buffered-file)
     4087 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     4093     # check output
     4094     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
     4095     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
     4096     # check that stop(1) was called
     4097     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
     4098     # don't restore from ebp
     4099     81 0/subop/add %esp 8/imm32
     4100     # . epilogue
     4101     5d/pop-to-ebp
     4102     c3/return
     4103
     4104 test-convert-function-with-local-var-in-block:
     4105     # . prologue
     4106     55/push-ebp
     4107     89/<- %ebp 4/r32/esp
     4108     # setup
     4109     (clear-stream _test-input-stream)
     4110     (clear-stream $_test-input-buffered-file->buffer)
     4111     (clear-stream _test-output-stream)
     4112     (clear-stream $_test-output-buffered-file->buffer)
     4113     #
     4114     (write _test-input-stream "fn foo {\n")
     4115     (write _test-input-stream "  {\n")
     4116     (write _test-input-stream "    var x: int\n")
     4117     (write _test-input-stream "    increment x\n")
     4118     (write _test-input-stream "  }\n")
     4119     (write _test-input-stream "}\n")
     4120     # convert
     4121     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4122     (flush _test-output-buffered-file)
     4123 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4129     # check output
     4130     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
     4131     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
     4132     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
     4133     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
     4134     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
     4135     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
     4136     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
     4137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
     4138     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
     4139     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
     4140     (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")
     4141     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
     4142     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
     4143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
     4144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
     4145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
     4146     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
     4147     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
     4148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
     4149     # . epilogue
     4150     89/<- %esp 5/r32/ebp
     4151     5d/pop-to-ebp
     4152     c3/return
     4153
     4154 test-convert-function-with-local-var-in-mem-after-block:
     4155     # . prologue
     4156     55/push-ebp
     4157     89/<- %ebp 4/r32/esp
     4158     # setup
     4159     (clear-stream _test-input-stream)
     4160     (clear-stream $_test-input-buffered-file->buffer)
     4161     (clear-stream _test-output-stream)
     4162     (clear-stream $_test-output-buffered-file->buffer)
     4163     #
     4164     (write _test-input-stream "fn foo {\n")
     4165     (write _test-input-stream "  {\n")
     4166     (write _test-input-stream "    var y: int\n")
     4167     (write _test-input-stream "  }\n")
     4168     (write _test-input-stream "  var x: int\n")
     4169     (write _test-input-stream "  increment x\n")
     4170     (write _test-input-stream "}\n")
     4171     # convert
     4172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4173     (flush _test-output-buffered-file)
     4174 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4180     # check output
     4181     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
     4182     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
     4183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
     4184     (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")
     4185     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
     4186     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
     4187     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
     4188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
     4189     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
     4190     (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")
     4191     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
     4192     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
     4193     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
     4194     (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")
     4195     (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")
     4196     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
     4197     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
     4198     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
     4199     (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")
     4200     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
     4201     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
     4202     # . epilogue
     4203     89/<- %esp 5/r32/ebp
     4204     5d/pop-to-ebp
     4205     c3/return
     4206
     4207 test-convert-function-with-local-var-in-named-block:
     4208     # . prologue
     4209     55/push-ebp
     4210     89/<- %ebp 4/r32/esp
     4211     # setup
     4212     (clear-stream _test-input-stream)
     4213     (clear-stream $_test-input-buffered-file->buffer)
     4214     (clear-stream _test-output-stream)
     4215     (clear-stream $_test-output-buffered-file->buffer)
     4216     #
     4217     (write _test-input-stream "fn foo {\n")
     4218     (write _test-input-stream "  $bar: {\n")
     4219     (write _test-input-stream "    var x: int\n")
     4220     (write _test-input-stream "    increment x\n")
     4221     (write _test-input-stream "  }\n")
     4222     (write _test-input-stream "}\n")
     4223     # convert
     4224     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4225     (flush _test-output-buffered-file)
     4226 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4232     # check output
     4233     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
     4234     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
     4235     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
     4236     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
     4237     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
     4238     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
     4239     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
     4240     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
     4241     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
     4242     (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")
     4243     (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")
     4244     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
     4245     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
     4246     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
     4247     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
     4248     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
     4249     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
     4250     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
     4251     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
     4252     # . epilogue
     4253     89/<- %esp 5/r32/ebp
     4254     5d/pop-to-ebp
     4255     c3/return
     4256
     4257 test-unknown-variable-in-named-block:
     4258     # . prologue
     4259     55/push-ebp
     4260     89/<- %ebp 4/r32/esp
     4261     # setup
     4262     (clear-stream _test-input-stream)
     4263     (clear-stream $_test-input-buffered-file->buffer)
     4264     (clear-stream _test-output-stream)
     4265     (clear-stream $_test-output-buffered-file->buffer)
     4266     (clear-stream _test-error-stream)
     4267     (clear-stream $_test-error-buffered-file->buffer)
     4268     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     4269     68/push 0/imm32
     4270     68/push 0/imm32
     4271     89/<- %edx 4/r32/esp
     4272     (tailor-exit-descriptor %edx 0x10)
     4273     #
     4274     (write _test-input-stream "fn foo {\n")
     4275     (write _test-input-stream "  $a: {\n")
     4276     (write _test-input-stream "    compare x, 0\n")
     4277     (write _test-input-stream "  }\n")
     4278     (write _test-input-stream "}\n")
     4279     # convert
     4280     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     4281     # registers except esp clobbered at this point
     4282     # restore ed
     4283     89/<- %edx 4/r32/esp
     4284     (flush _test-output-buffered-file)
     4285     (flush _test-error-buffered-file)
     4286 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     4292     # check output
     4293     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
     4294     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
     4295     # check that stop(1) was called
     4296     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
     4297     # don't restore from ebp
     4298     81 0/subop/add %esp 8/imm32
     4299     # . epilogue
     4300     5d/pop-to-ebp
     4301     c3/return
     4302
     4303 test-always-shadow-outermost-reg-vars-in-function:
     4304     # . prologue
     4305     55/push-ebp
     4306     89/<- %ebp 4/r32/esp
     4307     # setup
     4308     (clear-stream _test-input-stream)
     4309     (clear-stream $_test-input-buffered-file->buffer)
     4310     (clear-stream _test-output-stream)
     4311     (clear-stream $_test-output-buffered-file->buffer)
     4312     #
     4313     (write _test-input-stream "fn foo {\n")
     4314     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4315     (write _test-input-stream "}\n")
     4316     # convert
     4317     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4318     (flush _test-output-buffered-file)
     4319 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4325     # check output
     4326     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
     4327     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
     4328     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
     4329     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
     4330     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
     4331     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
     4332     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
     4333     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
     4334     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
     4335     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
     4336     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
     4337     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
     4338     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
     4339     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
     4340     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
     4341     # . epilogue
     4342     89/<- %esp 5/r32/ebp
     4343     5d/pop-to-ebp
     4344     c3/return
     4345
     4346 test-shadow-local:
     4347     # . prologue
     4348     55/push-ebp
     4349     89/<- %ebp 4/r32/esp
     4350     # setup
     4351     (clear-stream _test-input-stream)
     4352     (clear-stream $_test-input-buffered-file->buffer)
     4353     (clear-stream _test-output-stream)
     4354     (clear-stream $_test-output-buffered-file->buffer)
     4355     #
     4356     (write _test-input-stream "fn foo {\n")
     4357     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4358     (write _test-input-stream "  {\n")
     4359     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
     4360     (write _test-input-stream "  }\n")
     4361     (write _test-input-stream "  x <- increment\n")
     4362     (write _test-input-stream "}\n")
     4363     # convert
     4364     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4365     (flush _test-output-buffered-file)
     4366 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4372     # check output
     4373     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
     4374     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
     4375     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
     4376     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
     4377     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
     4378     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
     4379     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
     4380     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
     4381     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
     4382     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
     4383     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
     4384     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
     4385     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
     4386     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
     4387     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
     4388     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
     4389     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
     4390     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
     4391     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
     4392     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
     4393     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
     4394     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
     4395     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
     4396     # . epilogue
     4397     89/<- %esp 5/r32/ebp
     4398     5d/pop-to-ebp
     4399     c3/return
     4400
     4401 test-shadow-name:
     4402     # . prologue
     4403     55/push-ebp
     4404     89/<- %ebp 4/r32/esp
     4405     # setup
     4406     (clear-stream _test-input-stream)
     4407     (clear-stream $_test-input-buffered-file->buffer)
     4408     (clear-stream _test-output-stream)
     4409     (clear-stream $_test-output-buffered-file->buffer)
     4410     #
     4411     (write _test-input-stream "fn foo {\n")
     4412     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4413     (write _test-input-stream "  {\n")
     4414     (write _test-input-stream "    var x/edx: int <- copy 4\n")
     4415     (write _test-input-stream "  }\n")
     4416     (write _test-input-stream "  x <- increment\n")
     4417     (write _test-input-stream "}\n")
     4418     # convert
     4419     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4420     (flush _test-output-buffered-file)
     4421 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4427     # check output
     4428     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
     4429     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
     4430     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
     4431     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
     4432     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
     4433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
     4434     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
     4435     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
     4436     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
     4437     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
     4438     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
     4439     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
     4440     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
     4441     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
     4442     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
     4443     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
     4444     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
     4445     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
     4446     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
     4447     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
     4448     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
     4449     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
     4450     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
     4451     # . epilogue
     4452     89/<- %esp 5/r32/ebp
     4453     5d/pop-to-ebp
     4454     c3/return
     4455
     4456 test-shadow-name-2:
     4457     # . prologue
     4458     55/push-ebp
     4459     89/<- %ebp 4/r32/esp
     4460     # setup
     4461     (clear-stream _test-input-stream)
     4462     (clear-stream $_test-input-buffered-file->buffer)
     4463     (clear-stream _test-output-stream)
     4464     (clear-stream $_test-output-buffered-file->buffer)
     4465     #
     4466     (write _test-input-stream "fn foo {\n")
     4467     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4468     (write _test-input-stream "  {\n")
     4469     (write _test-input-stream "    var x/edx: int <- copy 4\n")
     4470     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
     4471     (write _test-input-stream "  }\n")
     4472     (write _test-input-stream "  x <- increment\n")
     4473     (write _test-input-stream "}\n")
     4474     # convert
     4475     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4476     (flush _test-output-buffered-file)
     4477 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4483     # check output
     4484     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
     4485     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
     4486     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
     4487     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
     4488     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
     4489     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
     4490     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
     4491     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
     4492     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
     4493     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
     4494     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
     4495     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
     4496     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
     4497     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
     4498     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
     4499     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
     4500     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
     4501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
     4502     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
     4503     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
     4504     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
     4505     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
     4506     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
     4507     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
     4508     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
     4509     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
     4510     # . epilogue
     4511     89/<- %esp 5/r32/ebp
     4512     5d/pop-to-ebp
     4513     c3/return
     4514
     4515 test-do-not-spill-same-register-in-block:
     4516     # . prologue
     4517     55/push-ebp
     4518     89/<- %ebp 4/r32/esp
     4519     # setup
     4520     (clear-stream _test-input-stream)
     4521     (clear-stream $_test-input-buffered-file->buffer)
     4522     (clear-stream _test-output-stream)
     4523     (clear-stream $_test-output-buffered-file->buffer)
     4524     #
     4525     (write _test-input-stream "fn foo {\n")
     4526     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4527     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     4528     (write _test-input-stream "  y <- increment\n")
     4529     (write _test-input-stream "}\n")
     4530     # convert
     4531     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4532     (flush _test-output-buffered-file)
     4533 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4539     # check output
     4540     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
     4541     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
     4542     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
     4543     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
     4544     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
     4545     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
     4546     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
     4547     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
     4548     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
     4549     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
     4550     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
     4551     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
     4552     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
     4553     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
     4554     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
     4555     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
     4556     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
     4557     # . epilogue
     4558     89/<- %esp 5/r32/ebp
     4559     5d/pop-to-ebp
     4560     c3/return
     4561
     4562 test-spill-different-register-in-block:
     4563     # . prologue
     4564     55/push-ebp
     4565     89/<- %ebp 4/r32/esp
     4566     # setup
     4567     (clear-stream _test-input-stream)
     4568     (clear-stream $_test-input-buffered-file->buffer)
     4569     (clear-stream _test-output-stream)
     4570     (clear-stream $_test-output-buffered-file->buffer)
     4571     #
     4572     (write _test-input-stream "fn foo {\n")
     4573     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     4574     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     4575     (write _test-input-stream "  y <- increment\n")
     4576     (write _test-input-stream "}\n")
     4577     # convert
     4578     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4579     (flush _test-output-buffered-file)
     4580 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4586     # check output
     4587     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
     4588     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
     4589     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
     4590     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
     4591     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
     4592     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
     4593     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
     4594     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
     4595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
     4596     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
     4597     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
     4598     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
     4599     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
     4600     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
     4601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
     4602     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
     4603     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
     4604     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
     4605     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
     4606     # . epilogue
     4607     89/<- %esp 5/r32/ebp
     4608     5d/pop-to-ebp
     4609     c3/return
     4610
     4611 test-convert-function-with-branches-in-block:
     4612     # . prologue
     4613     55/push-ebp
     4614     89/<- %ebp 4/r32/esp
     4615     # setup
     4616     (clear-stream _test-input-stream)
     4617     (clear-stream $_test-input-buffered-file->buffer)
     4618     (clear-stream _test-output-stream)
     4619     (clear-stream $_test-output-buffered-file->buffer)
     4620     #
     4621     (write _test-input-stream "fn foo x: int {\n")
     4622     (write _test-input-stream "  {\n")
     4623     (write _test-input-stream "    break-if->=\n")
     4624     (write _test-input-stream "    loop-if-addr<\n")
     4625     (write _test-input-stream "    increment x\n")
     4626     (write _test-input-stream "    loop\n")
     4627     (write _test-input-stream "  }\n")
     4628     (write _test-input-stream "}\n")
     4629     # convert
     4630     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4631     (flush _test-output-buffered-file)
     4632 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4638     # check output
     4639     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
     4640     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
     4641     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
     4642     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
     4643     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
     4644     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
     4645     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
     4646     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
     4647     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
     4648     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
     4649     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
     4650     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
     4651     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
     4652     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
     4653     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
     4654     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
     4655     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
     4656     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
     4657     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
     4658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
     4659     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
     4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
     4661     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
     4662     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
     4663     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
     4664     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
     4665     # . epilogue
     4666     89/<- %esp 5/r32/ebp
     4667     5d/pop-to-ebp
     4668     c3/return
     4669
     4670 test-convert-function-with-branches-in-block-2:
     4671     # . prologue
     4672     55/push-ebp
     4673     89/<- %ebp 4/r32/esp
     4674     # setup
     4675     (clear-stream _test-input-stream)
     4676     (clear-stream $_test-input-buffered-file->buffer)
     4677     (clear-stream _test-output-stream)
     4678     (clear-stream $_test-output-buffered-file->buffer)
     4679     #
     4680     (write _test-input-stream "fn foo x: int {\n")
     4681     (write _test-input-stream "  {\n")
     4682     (write _test-input-stream "    break-if->=\n")
     4683     (write _test-input-stream "    loop-if-float<\n")
     4684     (write _test-input-stream "    increment x\n")
     4685     (write _test-input-stream "    loop\n")
     4686     (write _test-input-stream "  }\n")
     4687     (write _test-input-stream "}\n")
     4688     # convert
     4689     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4690     (flush _test-output-buffered-file)
     4691 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4697     # check output
     4698     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
     4699     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
     4700     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
     4701     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
     4702     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
     4703     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
     4704     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
     4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
     4706     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
     4707     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
     4708     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
     4709     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
     4710     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
     4711     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
     4712     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
     4713     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
     4714     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
     4715     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
     4716     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
     4717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
     4718     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
     4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
     4720     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
     4721     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
     4722     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
     4723     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
     4724     # . epilogue
     4725     89/<- %esp 5/r32/ebp
     4726     5d/pop-to-ebp
     4727     c3/return
     4728
     4729 test-convert-function-with-branches-in-named-block:
     4730     # . prologue
     4731     55/push-ebp
     4732     89/<- %ebp 4/r32/esp
     4733     # setup
     4734     (clear-stream _test-input-stream)
     4735     (clear-stream $_test-input-buffered-file->buffer)
     4736     (clear-stream _test-output-stream)
     4737     (clear-stream $_test-output-buffered-file->buffer)
     4738     #
     4739     (write _test-input-stream "fn foo x: int {\n")
     4740     (write _test-input-stream "  $bar: {\n")
     4741     (write _test-input-stream "    break-if->= $bar\n")
     4742     (write _test-input-stream "    loop-if-addr< $bar\n")
     4743     (write _test-input-stream "    increment x\n")
     4744     (write _test-input-stream "    loop\n")
     4745     (write _test-input-stream "  }\n")
     4746     (write _test-input-stream "}\n")
     4747     # convert
     4748     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4749     (flush _test-output-buffered-file)
     4750 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4756     # check output
     4757     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
     4758     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
     4759     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
     4760     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
     4761     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
     4762     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
     4763     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
     4764     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
     4765     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
     4766     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
     4767     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
     4768     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
     4769     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
     4770     (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")
     4771     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
     4772     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
     4773     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
     4774     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
     4775     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
     4776     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
     4777     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
     4778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
     4779     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
     4780     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
     4781     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
     4782     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
     4783     # . epilogue
     4784     89/<- %esp 5/r32/ebp
     4785     5d/pop-to-ebp
     4786     c3/return
     4787
     4788 test-convert-function-with-var-in-nested-block:
     4789     # . prologue
     4790     55/push-ebp
     4791     89/<- %ebp 4/r32/esp
     4792     # setup
     4793     (clear-stream _test-input-stream)
     4794     (clear-stream $_test-input-buffered-file->buffer)
     4795     (clear-stream _test-output-stream)
     4796     (clear-stream $_test-output-buffered-file->buffer)
     4797     #
     4798     (write _test-input-stream "fn foo x: int {\n")
     4799     (write _test-input-stream "  {\n")
     4800     (write _test-input-stream "    {\n")
     4801     (write _test-input-stream "      var x: int\n")
     4802     (write _test-input-stream "      increment x\n")
     4803     (write _test-input-stream "    }\n")
     4804     (write _test-input-stream "  }\n")
     4805     (write _test-input-stream "}\n")
     4806     # convert
     4807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4808     (flush _test-output-buffered-file)
     4809 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4815     # check output
     4816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
     4817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
     4818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
     4819     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
     4820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
     4821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
     4822     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
     4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
     4824     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
     4825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
     4826     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
     4827     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
     4828     (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")
     4829     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
     4830     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
     4831     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
     4832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
     4833     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
     4834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
     4835     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
     4836     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
     4837     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
     4838     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
     4839     # . epilogue
     4840     89/<- %esp 5/r32/ebp
     4841     5d/pop-to-ebp
     4842     c3/return
     4843
     4844 test-convert-function-with-multiple-vars-in-nested-blocks:
     4845     # . prologue
     4846     55/push-ebp
     4847     89/<- %ebp 4/r32/esp
     4848     # setup
     4849     (clear-stream _test-input-stream)
     4850     (clear-stream $_test-input-buffered-file->buffer)
     4851     (clear-stream _test-output-stream)
     4852     (clear-stream $_test-output-buffered-file->buffer)
     4853     #
     4854     (write _test-input-stream "fn foo x: int {\n")
     4855     (write _test-input-stream "  {\n")
     4856     (write _test-input-stream "    var x/eax: int <- copy 0\n")
     4857     (write _test-input-stream "    {\n")
     4858     (write _test-input-stream "      var y: int\n")
     4859     (write _test-input-stream "      x <- add y\n")
     4860     (write _test-input-stream "    }\n")
     4861     (write _test-input-stream "  }\n")
     4862     (write _test-input-stream "}\n")
     4863     # convert
     4864     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4865     (flush _test-output-buffered-file)
     4866 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4872     # check output
     4873     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
     4874     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
     4875     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
     4876     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
     4877     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
     4878     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
     4879     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
     4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
     4881     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
     4882     (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")
     4883     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
     4884     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
     4885     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
     4886     (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")
     4887     (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")
     4888     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
     4889     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
     4890     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
     4891     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
     4892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
     4893     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
     4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
     4895     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
     4896     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
     4897     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
     4898     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
     4899     # . epilogue
     4900     89/<- %esp 5/r32/ebp
     4901     5d/pop-to-ebp
     4902     c3/return
     4903
     4904 test-convert-function-with-branches-and-local-vars:
     4905     # A conditional 'break' after a 'var' in a block is converted into a
     4906     # nested block that performs all necessary cleanup before jumping. This
     4907     # results in some ugly code duplication.
     4908     # . prologue
     4909     55/push-ebp
     4910     89/<- %ebp 4/r32/esp
     4911     # setup
     4912     (clear-stream _test-input-stream)
     4913     (clear-stream $_test-input-buffered-file->buffer)
     4914     (clear-stream _test-output-stream)
     4915     (clear-stream $_test-output-buffered-file->buffer)
     4916     #
     4917     (write _test-input-stream "fn foo {\n")
     4918     (write _test-input-stream "  {\n")
     4919     (write _test-input-stream "    var x: int\n")
     4920     (write _test-input-stream "    break-if->=\n")
     4921     (write _test-input-stream "    increment x\n")
     4922     (write _test-input-stream "  }\n")
     4923     (write _test-input-stream "}\n")
     4924     # convert
     4925     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4926     (flush _test-output-buffered-file)
     4927 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4933     # check output
     4934     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
     4935     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
     4936     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
     4937     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
     4938     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
     4939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
     4940     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
     4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
     4942     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
     4943     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
     4944     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
     4945     (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")
     4946     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
     4947     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
     4948     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
     4949     (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")
     4950     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
     4951     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
     4952     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
     4953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
     4954     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
     4955     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
     4956     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
     4957     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
     4958     # . epilogue
     4959     89/<- %esp 5/r32/ebp
     4960     5d/pop-to-ebp
     4961     c3/return
     4962
     4963 test-convert-function-with-conditional-loops-and-local-vars:
     4964     # A conditional 'loop' after a 'var' in a block is converted into a nested
     4965     # block that performs all necessary cleanup before jumping. This results
     4966     # in some ugly code duplication.
     4967     # . prologue
     4968     55/push-ebp
     4969     89/<- %ebp 4/r32/esp
     4970     # setup
     4971     (clear-stream _test-input-stream)
     4972     (clear-stream $_test-input-buffered-file->buffer)
     4973     (clear-stream _test-output-stream)
     4974     (clear-stream $_test-output-buffered-file->buffer)
     4975     #
     4976     (write _test-input-stream "fn foo {\n")
     4977     (write _test-input-stream "  {\n")
     4978     (write _test-input-stream "    var x: int\n")
     4979     (write _test-input-stream "    loop-if->=\n")
     4980     (write _test-input-stream "    increment x\n")
     4981     (write _test-input-stream "  }\n")
     4982     (write _test-input-stream "}\n")
     4983     # convert
     4984     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4985     (flush _test-output-buffered-file)
     4986 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4992     # check output
     4993     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
     4994     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
     4995     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
     4996     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
     4997     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
     4998     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
     4999     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
     5000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
     5001     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
     5002     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
     5003     (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")
     5004     (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")
     5005     (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")
     5006     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
     5007     (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")
     5008     (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")
     5009     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
     5010     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
     5011     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
     5012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
     5013     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
     5014     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
     5015     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
     5016     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
     5017     # . epilogue
     5018     89/<- %esp 5/r32/ebp
     5019     5d/pop-to-ebp
     5020     c3/return
     5021
     5022 test-convert-function-with-unconditional-loops-and-local-vars:
     5023     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
     5024     # regular block cleanup. Any instructions after 'loop' are dead and
     5025     # therefore skipped.
     5026     # . prologue
     5027     55/push-ebp
     5028     89/<- %ebp 4/r32/esp
     5029     # setup
     5030     (clear-stream _test-input-stream)
     5031     (clear-stream $_test-input-buffered-file->buffer)
     5032     (clear-stream _test-output-stream)
     5033     (clear-stream $_test-output-buffered-file->buffer)
     5034     #
     5035     (write _test-input-stream "fn foo {\n")
     5036     (write _test-input-stream "  {\n")
     5037     (write _test-input-stream "    var x: int\n")
     5038     (write _test-input-stream "    loop\n")
     5039     (write _test-input-stream "    increment x\n")
     5040     (write _test-input-stream "  }\n")
     5041     (write _test-input-stream "}\n")
     5042     # convert
     5043     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5044     (flush _test-output-buffered-file)
     5045 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5051     # check output
     5052     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
     5053     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
     5054     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
     5055     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
     5056     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
     5057     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
     5058     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
     5059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
     5060     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
     5061     (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")
     5062     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
     5063     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
     5064     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
     5065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
     5066     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
     5067     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
     5068     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
     5069     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
     5070     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
     5071     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
     5072     # . epilogue
     5073     89/<- %esp 5/r32/ebp
     5074     5d/pop-to-ebp
     5075     c3/return
     5076
     5077 test-convert-function-with-branches-and-loops-and-local-vars:
     5078     # . prologue
     5079     55/push-ebp
     5080     89/<- %ebp 4/r32/esp
     5081     # setup
     5082     (clear-stream _test-input-stream)
     5083     (clear-stream $_test-input-buffered-file->buffer)
     5084     (clear-stream _test-output-stream)
     5085     (clear-stream $_test-output-buffered-file->buffer)
     5086     #
     5087     (write _test-input-stream "fn foo {\n")
     5088     (write _test-input-stream "  {\n")
     5089     (write _test-input-stream "    var x: int\n")
     5090     (write _test-input-stream "    break-if->=\n")
     5091     (write _test-input-stream "    increment x\n")
     5092     (write _test-input-stream "    loop\n")
     5093     (write _test-input-stream "  }\n")
     5094     (write _test-input-stream "}\n")
     5095     # convert
     5096     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5097     (flush _test-output-buffered-file)
     5098 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5104     # check output
     5105     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
     5106     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
     5107     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
     5108     (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")
     5109     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
     5110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
     5111     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
     5112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
     5113     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
     5114     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
     5115     (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")
     5116     (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")
     5117     (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")
     5118     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
     5119     (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")
     5120     (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")
     5121     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
     5122     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
     5123     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
     5124     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
     5125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
     5126     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
     5127     (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")
     5128     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
     5129     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
     5130     # . epilogue
     5131     89/<- %esp 5/r32/ebp
     5132     5d/pop-to-ebp
     5133     c3/return
     5134
     5135 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
     5136     # . prologue
     5137     55/push-ebp
     5138     89/<- %ebp 4/r32/esp
     5139     # setup
     5140     (clear-stream _test-input-stream)
     5141     (clear-stream $_test-input-buffered-file->buffer)
     5142     (clear-stream _test-output-stream)
     5143     (clear-stream $_test-output-buffered-file->buffer)
     5144     #
     5145     (write _test-input-stream "fn foo {\n")
     5146     (write _test-input-stream "  a: {\n")
     5147     (write _test-input-stream "    var x: int\n")
     5148     (write _test-input-stream "    {\n")
     5149     (write _test-input-stream "      var y: int\n")
     5150     (write _test-input-stream "      break-if->= a\n")
     5151     (write _test-input-stream "      increment x\n")
     5152     (write _test-input-stream "      loop\n")
     5153     (write _test-input-stream "    }\n")
     5154     (write _test-input-stream "  }\n")
     5155     (write _test-input-stream "}\n")
     5156     # convert
     5157     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5158     (flush _test-output-buffered-file)
     5159 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5165     # check output
     5166     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
     5167     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
     5168     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
     5169     (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")
     5170     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
     5171     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
     5172     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
     5173     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
     5174     (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")
     5175     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
     5176     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
     5177     (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")
     5178     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
     5179     (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")
     5180     (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")
     5181     (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")
     5182     (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")
     5183     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
     5184     (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")
     5185     (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")
     5186     (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")
     5187     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
     5188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
     5189     (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")
     5190     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
     5191     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
     5192     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
     5193     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
     5194     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
     5195     (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")
     5196     (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")
     5197     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
     5198     # . epilogue
     5199     89/<- %esp 5/r32/ebp
     5200     5d/pop-to-ebp
     5201     c3/return
     5202
     5203 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
     5204     # . prologue
     5205     55/push-ebp
     5206     89/<- %ebp 4/r32/esp
     5207     # setup
     5208     (clear-stream _test-input-stream)
     5209     (clear-stream $_test-input-buffered-file->buffer)
     5210     (clear-stream _test-output-stream)
     5211     (clear-stream $_test-output-buffered-file->buffer)
     5212     # non-local conditional branch from a block without a local variable,
     5213     # unwinding a local on the stack
     5214     (write _test-input-stream "fn foo {\n")
     5215     (write _test-input-stream "  a: {\n")
     5216     (write _test-input-stream "    var x: int\n")
     5217     (write _test-input-stream "    {\n")
     5218     (write _test-input-stream "      break-if->= a\n")
     5219     (write _test-input-stream "    }\n")
     5220     (write _test-input-stream "  }\n")
     5221     (write _test-input-stream "}\n")
     5222     # convert
     5223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5224     (flush _test-output-buffered-file)
     5225 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5231     # check output
     5232     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
     5233     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
     5234     (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")
     5235     (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")
     5236     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
     5237     (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")
     5238     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
     5239     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
     5240     (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")
     5241     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
     5242     (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")
     5243     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
     5244     (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")
     5245     (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")
     5246     (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")
     5247     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
     5248     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
     5249     (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")
     5250     (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")
     5251     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
     5252     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
     5253     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
     5254     (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")
     5255     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
     5256     (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")
     5257     (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")
     5258     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
     5259     # . epilogue
     5260     89/<- %esp 5/r32/ebp
     5261     5d/pop-to-ebp
     5262     c3/return
     5263
     5264 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
     5265     # . prologue
     5266     55/push-ebp
     5267     89/<- %ebp 4/r32/esp
     5268     # setup
     5269     (clear-stream _test-input-stream)
     5270     (clear-stream $_test-input-buffered-file->buffer)
     5271     (clear-stream _test-output-stream)
     5272     (clear-stream $_test-output-buffered-file->buffer)
     5273     # non-local unconditional branch from a block without a local variable,
     5274     # unwinding a local on the stack
     5275     (write _test-input-stream "fn foo {\n")
     5276     (write _test-input-stream "  a: {\n")
     5277     (write _test-input-stream "    var x: int\n")
     5278     (write _test-input-stream "    {\n")
     5279     (write _test-input-stream "      break a\n")
     5280     (write _test-input-stream "    }\n")
     5281     (write _test-input-stream "  }\n")
     5282     (write _test-input-stream "}\n")
     5283     # convert
     5284     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5285     (flush _test-output-buffered-file)
     5286 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5292     # check output
     5293     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
     5294     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
     5295     (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")
     5296     (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")
     5297     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
     5298     (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")
     5299     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
     5300     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
     5301     (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")
     5302     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
     5303     (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")
     5304     (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")
     5305     (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")
     5306     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
     5307     (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")
     5308     (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")
     5309     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
     5310     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
     5311     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
     5312     (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")
     5313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
     5314     (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")
     5315     (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")
     5316     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
     5317     # . epilogue
     5318     89/<- %esp 5/r32/ebp
     5319     5d/pop-to-ebp
     5320     c3/return
     5321
     5322 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
     5323     # . prologue
     5324     55/push-ebp
     5325     89/<- %ebp 4/r32/esp
     5326     # setup
     5327     (clear-stream _test-input-stream)
     5328     (clear-stream $_test-input-buffered-file->buffer)
     5329     (clear-stream _test-output-stream)
     5330     (clear-stream $_test-output-buffered-file->buffer)
     5331     #
     5332     (write _test-input-stream "fn foo {\n")
     5333     (write _test-input-stream "  a: {\n")
     5334     (write _test-input-stream "    var x/esi: int <- copy 0\n")
     5335     (write _test-input-stream "    {\n")
     5336     (write _test-input-stream "      break a\n")
     5337     (write _test-input-stream "    }\n")
     5338     (write _test-input-stream "  }\n")
     5339     (write _test-input-stream "}\n")
     5340     # convert
     5341     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5342     (flush _test-output-buffered-file)
     5343 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5349     # check output
     5350     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
     5351     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
     5352     (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")
     5353     (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")
     5354     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
     5355     (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")
     5356     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
     5357     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
     5358     (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")
     5359     (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")
     5360     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
     5361     (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")
     5362     (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")
     5363     (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")
     5364     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
     5365     (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")
     5366     (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")
     5367     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
     5368     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
     5369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
     5370     (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")
     5371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
     5372     (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")
     5373     (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")
     5374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
     5375     # . epilogue
     5376     89/<- %esp 5/r32/ebp
     5377     5d/pop-to-ebp
     5378     c3/return
     5379
     5380 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
     5381     # . prologue
     5382     55/push-ebp
     5383     89/<- %ebp 4/r32/esp
     5384     # setup
     5385     (clear-stream _test-input-stream)
     5386     (clear-stream $_test-input-buffered-file->buffer)
     5387     (clear-stream _test-output-stream)
     5388     (clear-stream $_test-output-buffered-file->buffer)
     5389     #
     5390     (write _test-input-stream "fn foo {\n")
     5391     (write _test-input-stream "  a: {\n")
     5392     (write _test-input-stream "    var x: int\n")
     5393     (write _test-input-stream "    {\n")
     5394     (write _test-input-stream "      var y: int\n")
     5395     (write _test-input-stream "      break a\n")
     5396     (write _test-input-stream "      increment x\n")
     5397     (write _test-input-stream "    }\n")
     5398     (write _test-input-stream "  }\n")
     5399     (write _test-input-stream "}\n")
     5400     # convert
     5401     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5402     (flush _test-output-buffered-file)
     5403 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5409     # check output
     5410     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
     5411     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
     5412     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
     5413     (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")
     5414     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
     5415     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
     5416     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
     5417     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
     5418     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
     5419     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
     5420     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
     5421     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
     5422     (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")
     5423     (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")
     5424     (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")
     5425     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
     5426     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
     5427     (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")
     5428     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
     5429     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
     5430     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
     5431     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
     5432     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
     5433     (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")
     5434     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
     5435     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
     5436     # . epilogue
     5437     89/<- %esp 5/r32/ebp
     5438     5d/pop-to-ebp
     5439     c3/return
     5440
     5441 test-convert-function-with-unconditional-break-and-local-vars:
     5442     # . prologue
     5443     55/push-ebp
     5444     89/<- %ebp 4/r32/esp
     5445     # setup
     5446     (clear-stream _test-input-stream)
     5447     (clear-stream $_test-input-buffered-file->buffer)
     5448     (clear-stream _test-output-stream)
     5449     (clear-stream $_test-output-buffered-file->buffer)
     5450     #
     5451     (write _test-input-stream "fn foo {\n")
     5452     (write _test-input-stream "  {\n")
     5453     (write _test-input-stream "    var x: int\n")
     5454     (write _test-input-stream "    {\n")
     5455     (write _test-input-stream "      var y: int\n")
     5456     (write _test-input-stream "      break\n")
     5457     (write _test-input-stream "      increment x\n")
     5458     (write _test-input-stream "    }\n")
     5459     (write _test-input-stream "  }\n")
     5460     (write _test-input-stream "}\n")
     5461     # convert
     5462     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5463     (flush _test-output-buffered-file)
     5464 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5470     # check output
     5471     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
     5472     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
     5473     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
     5474     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
     5475     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
     5476     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
     5477     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
     5478     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
     5479     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
     5480     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
     5481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
     5482     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
     5483     (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")
     5484     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
     5485     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
     5486     (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")
     5487     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
     5488     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
     5489     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
     5490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
     5491     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
     5492     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
     5493     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
     5494     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
     5495     # . epilogue
     5496     89/<- %esp 5/r32/ebp
     5497     5d/pop-to-ebp
     5498     c3/return
     5499
     5500 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
     5501     # . prologue
     5502     55/push-ebp
     5503     89/<- %ebp 4/r32/esp
     5504     # setup
     5505     (clear-stream _test-input-stream)
     5506     (clear-stream $_test-input-buffered-file->buffer)
     5507     (clear-stream _test-output-stream)
     5508     (clear-stream $_test-output-buffered-file->buffer)
     5509     #
     5510     (write _test-input-stream "fn foo {\n")
     5511     (write _test-input-stream "  a: {\n")
     5512     (write _test-input-stream "    var x: int\n")
     5513     (write _test-input-stream "    {\n")
     5514     (write _test-input-stream "      var y: int\n")
     5515     (write _test-input-stream "      loop a\n")
     5516     (write _test-input-stream "      increment x\n")
     5517     (write _test-input-stream "    }\n")
     5518     (write _test-input-stream "  }\n")
     5519     (write _test-input-stream "}\n")
     5520     # convert
     5521     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5522     (flush _test-output-buffered-file)
     5523 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5529     # check output
     5530     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
     5531     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
     5532     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
     5533     (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")
     5534     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
     5535     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
     5536     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
     5537     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
     5538     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
     5539     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
     5540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
     5541     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
     5542     (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")
     5543     (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")
     5544     (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")
     5545     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
     5546     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
     5547     (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")
     5548     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
     5549     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
     5550     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
     5551     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
     5552     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
     5553     (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")
     5554     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
     5555     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
     5556     # . epilogue
     5557     89/<- %esp 5/r32/ebp
     5558     5d/pop-to-ebp
     5559     c3/return
     5560
     5561 test-convert-function-with-local-array-var-in-mem:
     5562     # . prologue
     5563     55/push-ebp
     5564     89/<- %ebp 4/r32/esp
     5565     # setup
     5566     (clear-stream _test-input-stream)
     5567     (clear-stream $_test-input-buffered-file->buffer)
     5568     (clear-stream _test-output-stream)
     5569     (clear-stream $_test-output-buffered-file->buffer)
     5570     #
     5571     (write _test-input-stream "fn foo {\n")
     5572     (write _test-input-stream "  var x: (array int 3)\n")
     5573     (write _test-input-stream "}\n")
     5574     # convert
     5575     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5576     (flush _test-output-buffered-file)
     5577 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5583     # check output
     5584     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
     5585     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
     5586     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
     5587     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
     5588     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
     5589     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
     5590     # define x
     5591     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
     5592     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
     5593     # reclaim x
     5594     (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")
     5595     #
     5596     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
     5597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
     5598     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
     5599     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
     5600     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
     5601     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
     5602     # . epilogue
     5603     89/<- %esp 5/r32/ebp
     5604     5d/pop-to-ebp
     5605     c3/return
     5606
     5607 test-array-size-in-hex:
     5608     # . prologue
     5609     55/push-ebp
     5610     89/<- %ebp 4/r32/esp
     5611     # setup
     5612     (clear-stream _test-input-stream)
     5613     (clear-stream $_test-input-buffered-file->buffer)
     5614     (clear-stream _test-output-stream)
     5615     (clear-stream $_test-output-buffered-file->buffer)
     5616     (clear-stream _test-error-stream)
     5617     (clear-stream $_test-error-buffered-file->buffer)
     5618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     5619     68/push 0/imm32
     5620     68/push 0/imm32
     5621     89/<- %edx 4/r32/esp
     5622     (tailor-exit-descriptor %edx 0x10)
     5623     #
     5624     (write _test-input-stream "fn foo {\n")
     5625     (write _test-input-stream "  var x: (array int 10)\n")
     5626     (write _test-input-stream "}\n")
     5627     # convert
     5628     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     5629     # registers except esp clobbered at this point
     5630     # restore ed
     5631     89/<- %edx 4/r32/esp
     5632     (flush _test-output-buffered-file)
     5633     (flush _test-error-buffered-file)
     5634 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     5640     # check output
     5641     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
     5642     (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")
     5643     # check that stop(1) was called
     5644     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
     5645     # don't restore from ebp
     5646     81 0/subop/add %esp 8/imm32
     5647     # . epilogue
     5648     5d/pop-to-ebp
     5649     c3/return
     5650
     5651 test-array-size-with-metadata:
     5652     # . prologue
     5653     55/push-ebp
     5654     89/<- %ebp 4/r32/esp
     5655     # setup
     5656     (clear-stream _test-input-stream)
     5657     (clear-stream $_test-input-buffered-file->buffer)
     5658     (clear-stream _test-output-stream)
     5659     (clear-stream $_test-output-buffered-file->buffer)
     5660     #
     5661     (write _test-input-stream "fn foo {\n")
     5662     (write _test-input-stream "  var x: (array int 3/bar)\n")
     5663     (write _test-input-stream "}\n")
     5664     # convert
     5665     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5666     (flush _test-output-buffered-file)
     5667 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5673     # no errors
     5674     # . epilogue
     5675     89/<- %esp 5/r32/ebp
     5676     5d/pop-to-ebp
     5677     c3/return
     5678
     5679 test-convert-function-with-populate:
     5680     # . prologue
     5681     55/push-ebp
     5682     89/<- %ebp 4/r32/esp
     5683     # setup
     5684     (clear-stream _test-input-stream)
     5685     (clear-stream $_test-input-buffered-file->buffer)
     5686     (clear-stream _test-output-stream)
     5687     (clear-stream $_test-output-buffered-file->buffer)
     5688     #
     5689     (write _test-input-stream "fn foo {\n")
     5690     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
     5691     (write _test-input-stream "  populate x, 7\n")
     5692     (write _test-input-stream "}\n")
     5693     # convert
     5694     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5695     (flush _test-output-buffered-file)
     5696 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5702     # check output
     5703     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
     5704     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
     5705     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
     5706     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
     5707     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
     5708     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
     5709     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
     5710     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
     5711     (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)
     5712     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
     5713     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
     5714     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
     5715     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
     5716     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
     5717     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
     5718     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
     5719     # . epilogue
     5720     89/<- %esp 5/r32/ebp
     5721     5d/pop-to-ebp
     5722     c3/return
     5723
     5724 # special-case for size(byte) when allocating array
     5725 test-convert-function-with-local-array-of-bytes-in-mem:
     5726     # . prologue
     5727     55/push-ebp
     5728     89/<- %ebp 4/r32/esp
     5729     # setup
     5730     (clear-stream _test-input-stream)
     5731     (clear-stream $_test-input-buffered-file->buffer)
     5732     (clear-stream _test-output-stream)
     5733     (clear-stream $_test-output-buffered-file->buffer)
     5734     #
     5735     (write _test-input-stream "fn foo {\n")
     5736     (write _test-input-stream "  var x: (array byte 3)\n")
     5737     (write _test-input-stream "}\n")
     5738     # convert
     5739     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5740     (flush _test-output-buffered-file)
     5741 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5747     # check output
     5748     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
     5749     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
     5750     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
     5751     (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")
     5752     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
     5753     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
     5754     # define x
     5755     (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")
     5756     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
     5757     # reclaim x
     5758     (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")
     5759     #
     5760     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
     5761     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
     5762     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
     5763     (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")
     5764     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
     5765     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
     5766     # . epilogue
     5767     89/<- %esp 5/r32/ebp
     5768     5d/pop-to-ebp
     5769     c3/return
     5770
     5771 test-convert-address:
     5772     # . prologue
     5773     55/push-ebp
     5774     89/<- %ebp 4/r32/esp
     5775     # setup
     5776     (clear-stream _test-input-stream)
     5777     (clear-stream $_test-input-buffered-file->buffer)
     5778     (clear-stream _test-output-stream)
     5779     (clear-stream $_test-output-buffered-file->buffer)
     5780     #
     5781     (write _test-input-stream "fn foo {\n")
     5782     (write _test-input-stream "  var a: int\n")
     5783     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
     5784     (write _test-input-stream "}\n")
     5785     # convert
     5786     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5787     (flush _test-output-buffered-file)
     5788 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5794     # check output
     5795     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
     5796     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
     5797     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
     5798     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
     5799     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
     5800     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
     5801     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
     5802     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
     5803     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
     5804     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
     5805     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
     5806     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
     5807     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
     5808     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
     5809     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
     5810     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
     5811     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
     5812     # . epilogue
     5813     89/<- %esp 5/r32/ebp
     5814     5d/pop-to-ebp
     5815     c3/return
     5816
     5817 test-convert-floating-point-convert:
     5818     # . prologue
     5819     55/push-ebp
     5820     89/<- %ebp 4/r32/esp
     5821     # setup
     5822     (clear-stream _test-input-stream)
     5823     (clear-stream $_test-input-buffered-file->buffer)
     5824     (clear-stream _test-output-stream)
     5825     (clear-stream $_test-output-buffered-file->buffer)
     5826     #
     5827     (write _test-input-stream "fn foo {\n")
     5828     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     5829     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
     5830     (write _test-input-stream "}\n")
     5831     # convert
     5832     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5833     (flush _test-output-buffered-file)
     5834 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5840     # check output
     5841     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
     5842     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
     5843     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
     5844     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
     5845     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
     5846     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
     5847     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
     5848     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
     5849     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
     5850     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
     5851     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
     5852     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
     5853     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
     5854     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
     5855     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
     5856     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
     5857     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
     5858     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
     5859     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
     5860     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
     5861     # . epilogue
     5862     89/<- %esp 5/r32/ebp
     5863     5d/pop-to-ebp
     5864     c3/return
     5865
     5866 test-convert-floating-point-convert-2:
     5867     # . prologue
     5868     55/push-ebp
     5869     89/<- %ebp 4/r32/esp
     5870     # setup
     5871     (clear-stream _test-input-stream)
     5872     (clear-stream $_test-input-buffered-file->buffer)
     5873     (clear-stream _test-output-stream)
     5874     (clear-stream $_test-output-buffered-file->buffer)
     5875     #
     5876     (write _test-input-stream "fn foo {\n")
     5877     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     5878     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
     5879     (write _test-input-stream "  a <- convert b\n")
     5880     (write _test-input-stream "}\n")
     5881     # convert
     5882     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5883     (flush _test-output-buffered-file)
     5884 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5890     # check output
     5891     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
     5892     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
     5893     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
     5894     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
     5895     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
     5896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
     5897     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
     5898     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
     5899     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
     5900     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
     5901     (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")
     5902     (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")
     5903     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
     5904     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
     5905     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
     5906     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
     5907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
     5908     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
     5909     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
     5910     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
     5911     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
     5912     # . epilogue
     5913     89/<- %esp 5/r32/ebp
     5914     5d/pop-to-ebp
     5915     c3/return
     5916
     5917 test-convert-floating-point-operation:
     5918     # . prologue
     5919     55/push-ebp
     5920     89/<- %ebp 4/r32/esp
     5921     # setup
     5922     (clear-stream _test-input-stream)
     5923     (clear-stream $_test-input-buffered-file->buffer)
     5924     (clear-stream _test-output-stream)
     5925     (clear-stream $_test-output-buffered-file->buffer)
     5926     #
     5927     (write _test-input-stream "fn f {\n")
     5928     (write _test-input-stream "  var m: float\n")
     5929     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
     5930     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
     5931     (write _test-input-stream "  x <- copy y\n")
     5932     (write _test-input-stream "  copy-to m, y\n")
     5933     (write _test-input-stream "  x <- add y\n")
     5934     (write _test-input-stream "  x <- add m\n")
     5935     (write _test-input-stream "  x <- subtract y\n")
     5936     (write _test-input-stream "  x <- subtract m\n")
     5937     (write _test-input-stream "  x <- multiply y\n")
     5938     (write _test-input-stream "  x <- multiply m\n")
     5939     (write _test-input-stream "  x <- divide y\n")
     5940     (write _test-input-stream "  x <- divide m\n")
     5941     (write _test-input-stream "  x <- reciprocal y\n")
     5942     (write _test-input-stream "  x <- reciprocal m\n")
     5943     (write _test-input-stream "  x <- square-root y\n")
     5944     (write _test-input-stream "  x <- square-root m\n")
     5945     (write _test-input-stream "  x <- inverse-square-root y\n")
     5946     (write _test-input-stream "  x <- inverse-square-root m\n")
     5947     (write _test-input-stream "  x <- max y\n")
     5948     (write _test-input-stream "  x <- max m\n")
     5949     (write _test-input-stream "  x <- min y\n")
     5950     (write _test-input-stream "  x <- min m\n")
     5951     (write _test-input-stream "  compare x, y\n")
     5952     (write _test-input-stream "  compare x, m\n")
     5953     (write _test-input-stream "}\n")
     5954     # convert
     5955     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5956     (flush _test-output-buffered-file)
     5957 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5963     # check output
     5964     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
     5965     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
     5966     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
     5967     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
     5968     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
     5969     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
     5970     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
     5971     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
     5972     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
     5973     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
     5974     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
     5975     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
     5976     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
     5977     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
     5978     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
     5979     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
     5980     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
     5981     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
     5982     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
     5983     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
     5984     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
     5985     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
     5986     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
     5987     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
     5988     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
     5989     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
     5990     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
     5991     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
     5992     (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")
     5993     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
     5994     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
     5995     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
     5996     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
     5997     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
     5998     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
     5999     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
     6000     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
     6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
     6002     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
     6003     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
     6004     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
     6005     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
     6006     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
     6007     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
     6008     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
     6009     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
     6010     # . epilogue
     6011     89/<- %esp 5/r32/ebp
     6012     5d/pop-to-ebp
     6013     c3/return
     6014
     6015 test-convert-floating-point-dereferenced:
     6016     # . prologue
     6017     55/push-ebp
     6018     89/<- %ebp 4/r32/esp
     6019     # setup
     6020     (clear-stream _test-input-stream)
     6021     (clear-stream $_test-input-buffered-file->buffer)
     6022     (clear-stream _test-output-stream)
     6023     (clear-stream $_test-output-buffered-file->buffer)
     6024     #
     6025     (write _test-input-stream "fn f {\n")
     6026     (write _test-input-stream "  var m: float\n")
     6027     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
     6028     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
     6029     (write _test-input-stream "  x <- multiply *y\n")
     6030     (write _test-input-stream "}\n")
     6031     # convert
     6032     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6033     (flush _test-output-buffered-file)
     6034 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6040     # check output
     6041     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
     6042     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
     6043     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
     6044     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
     6045     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
     6046     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
     6047     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
     6048     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
     6049     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
     6050     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
     6051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
     6052     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
     6053     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
     6054     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
     6055     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
     6056     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
     6057     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
     6058     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
     6059     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
     6060     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
     6061     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
     6062     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
     6063     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
     6064     # . epilogue
     6065     89/<- %esp 5/r32/ebp
     6066     5d/pop-to-ebp
     6067     c3/return
     6068
     6069 test-convert-length-of-array:
     6070     # . prologue
     6071     55/push-ebp
     6072     89/<- %ebp 4/r32/esp
     6073     # setup
     6074     (clear-stream _test-input-stream)
     6075     (clear-stream $_test-input-buffered-file->buffer)
     6076     (clear-stream _test-output-stream)
     6077     (clear-stream $_test-output-buffered-file->buffer)
     6078     #
     6079     (write _test-input-stream "fn foo a: (addr array int) {\n")
     6080     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
     6081     (write _test-input-stream "  var c/eax: int <- length b\n")
     6082     (write _test-input-stream "}\n")
     6083     # convert
     6084     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6085     (flush _test-output-buffered-file)
     6086 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6092     # check output
     6093     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
     6094     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
     6095     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
     6096     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
     6097     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
     6098     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
     6099     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
     6100     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
     6101     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
     6102     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
     6103     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
     6104     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
     6105     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
     6106     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
     6107     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
     6108     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
     6109     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
     6110     # . epilogue
     6111     89/<- %esp 5/r32/ebp
     6112     5d/pop-to-ebp
     6113     c3/return
     6114
     6115 # special-case for size(byte) when computing array length
     6116 test-convert-length-of-array-of-bytes:
     6117     # . prologue
     6118     55/push-ebp
     6119     89/<- %ebp 4/r32/esp
     6120     # setup
     6121     (clear-stream _test-input-stream)
     6122     (clear-stream $_test-input-buffered-file->buffer)
     6123     (clear-stream _test-output-stream)
     6124     (clear-stream $_test-output-buffered-file->buffer)
     6125     #
     6126     (write _test-input-stream "fn foo a: (addr array byte) {\n")
     6127     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
     6128     (write _test-input-stream "  var c/eax: int <- length b\n")
     6129     (write _test-input-stream "}\n")
     6130     # convert
     6131     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6132     (flush _test-output-buffered-file)
     6133 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6139     # check output
     6140     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
     6141     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
     6142     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
     6143     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
     6144     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
     6145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
     6146     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
     6147     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
     6148     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
     6149     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
     6150     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
     6151     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
     6152     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
     6153     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
     6154     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
     6155     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
     6156     # . epilogue
     6157     89/<- %esp 5/r32/ebp
     6158     5d/pop-to-ebp
     6159     c3/return
     6160
     6161 test-convert-length-of-array-on-stack:
     6162     # . prologue
     6163     55/push-ebp
     6164     89/<- %ebp 4/r32/esp
     6165     # setup
     6166     (clear-stream _test-input-stream)
     6167     (clear-stream $_test-input-buffered-file->buffer)
     6168     (clear-stream _test-output-stream)
     6169     (clear-stream $_test-output-buffered-file->buffer)
     6170     #
     6171     (write _test-input-stream "fn foo {\n")
     6172     (write _test-input-stream "  var a: (array int 3)\n")
     6173     (write _test-input-stream "  var b/eax: int <- length a\n")
     6174     (write _test-input-stream "}\n")
     6175     # convert
     6176     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6177     (flush _test-output-buffered-file)
     6178 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6184     # check output
     6185     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
     6186     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
     6187     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
     6188     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
     6189     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
     6190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
     6191     # define x
     6192     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
     6193     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
     6194     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
     6195     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
     6196     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
     6197     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
     6198     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
     6199     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
     6200     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
     6201     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
     6202     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
     6203     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
     6204     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
     6205     # . epilogue
     6206     89/<- %esp 5/r32/ebp
     6207     5d/pop-to-ebp
     6208     c3/return
     6209
     6210 test-reg-var-def-with-read-of-same-register:
     6211     # . prologue
     6212     55/push-ebp
     6213     89/<- %ebp 4/r32/esp
     6214     # setup
     6215     (clear-stream _test-input-stream)
     6216     (clear-stream $_test-input-buffered-file->buffer)
     6217     (clear-stream _test-output-stream)
     6218     (clear-stream $_test-output-buffered-file->buffer)
     6219     (clear-stream _test-error-stream)
     6220     (clear-stream $_test-error-buffered-file->buffer)
     6221     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     6222     68/push 0/imm32
     6223     68/push 0/imm32
     6224     89/<- %edx 4/r32/esp
     6225     (tailor-exit-descriptor %edx 0x10)
     6226     #
     6227     (write _test-input-stream "fn foo {\n")
     6228     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     6229     (write _test-input-stream "  var y/eax: int <- add x\n")
     6230     (write _test-input-stream "}\n")
     6231     # convert
     6232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6233     # registers except esp could be clobbered at this point (though they shouldn't be)
     6234     # restore ed
     6235     89/<- %edx 4/r32/esp
     6236     (flush _test-output-buffered-file)
     6237     (flush _test-error-buffered-file)
     6238 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6244 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6250     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
     6251     # check output
     6252     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
     6253     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
     6254     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
     6255     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
     6256     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
     6257     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
     6258     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
     6259     (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")
     6260     (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")
     6261     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
     6262     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
     6263     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
     6264     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
     6265     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
     6266     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
     6267     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
     6268     # don't restore from ebp
     6269     81 0/subop/add %esp 8/imm32
     6270     # . epilogue
     6271     5d/pop-to-ebp
     6272     c3/return
     6273
     6274 test-convert-index-into-array:
     6275     # . prologue
     6276     55/push-ebp
     6277     89/<- %ebp 4/r32/esp
     6278     # setup
     6279     (clear-stream _test-input-stream)
     6280     (clear-stream $_test-input-buffered-file->buffer)
     6281     (clear-stream _test-output-stream)
     6282     (clear-stream $_test-output-buffered-file->buffer)
     6283     #
     6284     (write _test-input-stream "fn foo {\n")
     6285     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6286     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6287     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6288     (write _test-input-stream "}\n")
     6289     # convert
     6290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6291     (flush _test-output-buffered-file)
     6292 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6298     # check output
     6299     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
     6300     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
     6301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
     6302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
     6303     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
     6304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
     6305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
     6306     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
     6307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
     6308     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
     6309     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
     6310     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
     6311     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
     6312     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
     6313     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
     6314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
     6315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
     6316     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
     6317     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
     6318     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
     6319     # . epilogue
     6320     89/<- %esp 5/r32/ebp
     6321     5d/pop-to-ebp
     6322     c3/return
     6323
     6324 test-convert-index-into-array-of-bytes:
     6325     # . prologue
     6326     55/push-ebp
     6327     89/<- %ebp 4/r32/esp
     6328     # setup
     6329     (clear-stream _test-input-stream)
     6330     (clear-stream $_test-input-buffered-file->buffer)
     6331     (clear-stream _test-output-stream)
     6332     (clear-stream $_test-output-buffered-file->buffer)
     6333     #
     6334     (write _test-input-stream "fn foo {\n")
     6335     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6336     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6337     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
     6338     (write _test-input-stream "}\n")
     6339     # convert
     6340     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6341     (flush _test-output-buffered-file)
     6342 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6348     # check output
     6349     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
     6350     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
     6351     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
     6352     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
     6353     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
     6354     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
     6355     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
     6356     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
     6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
     6358     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
     6359     (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")
     6360     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/11")
     6361     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
     6362     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
     6363     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
     6364     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
     6365     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
     6366     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
     6367     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
     6368     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
     6369     # . epilogue
     6370     89/<- %esp 5/r32/ebp
     6371     5d/pop-to-ebp
     6372     c3/return
     6373
     6374 test-convert-index-into-array-with-literal:
     6375     # . prologue
     6376     55/push-ebp
     6377     89/<- %ebp 4/r32/esp
     6378     # setup
     6379     (clear-stream _test-input-stream)
     6380     (clear-stream $_test-input-buffered-file->buffer)
     6381     (clear-stream _test-output-stream)
     6382     (clear-stream $_test-output-buffered-file->buffer)
     6383     #
     6384     (write _test-input-stream "fn foo {\n")
     6385     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6386     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6387     (write _test-input-stream "}\n")
     6388     # convert
     6389     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6390     (flush _test-output-buffered-file)
     6391 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6397     # check output
     6398     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
     6399     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
     6400     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
     6401     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
     6402     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
     6403     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
     6404     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
     6405     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
     6406     (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")
     6407                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
     6408     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
     6409     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
     6410     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
     6411     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
     6412     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
     6413     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
     6414     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
     6415     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
     6416     # . epilogue
     6417     89/<- %esp 5/r32/ebp
     6418     5d/pop-to-ebp
     6419     c3/return
     6420
     6421 test-convert-index-into-array-of-bytes-with-literal:
     6422     # . prologue
     6423     55/push-ebp
     6424     89/<- %ebp 4/r32/esp
     6425     # setup
     6426     (clear-stream _test-input-stream)
     6427     (clear-stream $_test-input-buffered-file->buffer)
     6428     (clear-stream _test-output-stream)
     6429     (clear-stream $_test-output-buffered-file->buffer)
     6430     #
     6431     (write _test-input-stream "fn foo {\n")
     6432     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6433     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6434     (write _test-input-stream "}\n")
     6435     # convert
     6436     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6437     (flush _test-output-buffered-file)
     6438 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6444     # check output
     6445     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
     6446     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
     6447     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
     6448     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
     6449     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
     6450     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
     6451     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
     6452     (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")
     6453     (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")
     6454                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
     6455     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
     6456     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
     6457     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
     6458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
     6459     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
     6460     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
     6461     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
     6462     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
     6463     # . epilogue
     6464     89/<- %esp 5/r32/ebp
     6465     5d/pop-to-ebp
     6466     c3/return
     6467
     6468 test-convert-index-into-array-on-stack:
     6469     # . prologue
     6470     55/push-ebp
     6471     89/<- %ebp 4/r32/esp
     6472     # setup
     6473     (clear-stream _test-input-stream)
     6474     (clear-stream $_test-input-buffered-file->buffer)
     6475     (clear-stream _test-output-stream)
     6476     (clear-stream $_test-output-buffered-file->buffer)
     6477     #
     6478     (write _test-input-stream "fn foo {\n")
     6479     (write _test-input-stream "  var arr: (array int 3)\n")
     6480     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
     6481     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6482     (write _test-input-stream "}\n")
     6483     # convert
     6484     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6485     (flush _test-output-buffered-file)
     6486 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6492     # check output
     6493     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
     6494     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
     6495     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
     6496     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
     6497     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
     6498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
     6499     # var arr
     6500     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
     6501     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
     6502     # var idx
     6503     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
     6504     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
     6505     (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")
     6506     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
     6507     (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")
     6508     # reclaim idx
     6509     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
     6510     # reclaim arr
     6511     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
     6512     #
     6513     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
     6514     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
     6515     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
     6516     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
     6517     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
     6518     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
     6519     # . epilogue
     6520     89/<- %esp 5/r32/ebp
     6521     5d/pop-to-ebp
     6522     c3/return
     6523
     6524 test-convert-index-into-array-on-stack-with-literal:
     6525     # . prologue
     6526     55/push-ebp
     6527     89/<- %ebp 4/r32/esp
     6528     # setup
     6529     (clear-stream _test-input-stream)
     6530     (clear-stream $_test-input-buffered-file->buffer)
     6531     (clear-stream _test-output-stream)
     6532     (clear-stream $_test-output-buffered-file->buffer)
     6533     #
     6534     (write _test-input-stream "fn foo {\n")
     6535     (write _test-input-stream "  var arr: (array int 3)\n")
     6536     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6537     (write _test-input-stream "}\n")
     6538     # convert
     6539     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6540     (flush _test-output-buffered-file)
     6541 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6547     # check output
     6548     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
     6549     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
     6550     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
     6551     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
     6552     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
     6553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
     6554     # var arr
     6555     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
     6556     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
     6557     # var x
     6558     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
     6559     (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")
     6560     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
     6561     (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")
     6562     # reclaim x
     6563     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
     6564     # reclaim arr
     6565     (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")
     6566     #
     6567     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
     6568     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
     6569     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
     6570     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
     6571     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
     6572     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
     6573     # . epilogue
     6574     89/<- %esp 5/r32/ebp
     6575     5d/pop-to-ebp
     6576     c3/return
     6577
     6578 test-convert-index-into-array-of-bytes-on-stack-with-literal:
     6579     # . prologue
     6580     55/push-ebp
     6581     89/<- %ebp 4/r32/esp
     6582     # setup
     6583     (clear-stream _test-input-stream)
     6584     (clear-stream $_test-input-buffered-file->buffer)
     6585     (clear-stream _test-output-stream)
     6586     (clear-stream $_test-output-buffered-file->buffer)
     6587     #
     6588     (write _test-input-stream "fn foo {\n")
     6589     (write _test-input-stream "  var arr: (array byte 3)\n")
     6590     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6591     (write _test-input-stream "}\n")
     6592     # convert
     6593     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6594     (flush _test-output-buffered-file)
     6595 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6601     # check output
     6602     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
     6603     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
     6604     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
     6605     (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")
     6606     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
     6607     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
     6608     # var arr
     6609     (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")
     6610     (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")
     6611     # var x
     6612     (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")
     6613     (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")
     6614     # x is at (ebp-7) + 4 + 2 = ebp-1
     6615     (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")
     6616     # reclaim x
     6617     (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")
     6618     # reclaim arr
     6619     (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")
     6620     #
     6621     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
     6622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
     6623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
     6624     (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")
     6625     (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")
     6626     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
     6627     # . epilogue
     6628     89/<- %esp 5/r32/ebp
     6629     5d/pop-to-ebp
     6630     c3/return
     6631
     6632 test-convert-index-into-array-using-offset:
     6633     # . prologue
     6634     55/push-ebp
     6635     89/<- %ebp 4/r32/esp
     6636     # setup
     6637     (clear-stream _test-input-stream)
     6638     (clear-stream $_test-input-buffered-file->buffer)
     6639     (clear-stream _test-output-stream)
     6640     (clear-stream $_test-output-buffered-file->buffer)
     6641     #
     6642     (write _test-input-stream "fn foo {\n")
     6643     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6644     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6645     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6646     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6647     (write _test-input-stream "}\n")
     6648     # convert
     6649     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6650     (flush _test-output-buffered-file)
     6651 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6657     # check output
     6658     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
     6659     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
     6660     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
     6661     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
     6662     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
     6663     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
     6664     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
     6665     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
     6666     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
     6667     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
     6668     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
     6669     (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")
     6670     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/12")
     6671     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
     6672     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
     6673     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
     6674     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
     6675     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
     6676     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
     6677     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
     6678     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
     6679     # . epilogue
     6680     89/<- %esp 5/r32/ebp
     6681     5d/pop-to-ebp
     6682     c3/return
     6683
     6684 test-convert-index-into-array-of-bytes-using-offset:
     6685     # . prologue
     6686     55/push-ebp
     6687     89/<- %ebp 4/r32/esp
     6688     # setup
     6689     (clear-stream _test-input-stream)
     6690     (clear-stream $_test-input-buffered-file->buffer)
     6691     (clear-stream _test-output-stream)
     6692     (clear-stream $_test-output-buffered-file->buffer)
     6693     #
     6694     (write _test-input-stream "fn foo {\n")
     6695     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6696     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6697     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6698     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6699     (write _test-input-stream "}\n")
     6700     # convert
     6701     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6702     (flush _test-output-buffered-file)
     6703 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6709     # check output
     6710     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
     6711     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
     6712     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
     6713     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
     6714     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
     6715     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
     6716     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
     6717     (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")
     6718     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
     6719     (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")
     6720     (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")
     6721     (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")
     6722     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
     6723     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
     6724     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
     6725     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
     6726     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
     6727     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
     6728     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
     6729     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
     6730     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
     6731     # . epilogue
     6732     89/<- %esp 5/r32/ebp
     6733     5d/pop-to-ebp
     6734     c3/return
     6735
     6736 test-convert-index-into-array-using-offset-on-stack:
     6737     # . prologue
     6738     55/push-ebp
     6739     89/<- %ebp 4/r32/esp
     6740     # setup
     6741     (clear-stream _test-input-stream)
     6742     (clear-stream $_test-input-buffered-file->buffer)
     6743     (clear-stream _test-output-stream)
     6744     (clear-stream $_test-output-buffered-file->buffer)
     6745     #
     6746     (write _test-input-stream "fn foo {\n")
     6747     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6748     (write _test-input-stream "  var idx: int\n")
     6749     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6750     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6751     (write _test-input-stream "}\n")
     6752     # convert
     6753     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6754     (flush _test-output-buffered-file)
     6755 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6761     # check output
     6762     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
     6763     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
     6764     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
     6765     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
     6766     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
     6767     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
     6768     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
     6769     (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")
     6770     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
     6771     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
     6772     (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")
     6773     (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")
     6774     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
     6775     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
     6776     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/14")
     6777     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
     6778     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
     6779     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
     6780     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
     6781     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
     6782     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
     6783     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
     6784     # . epilogue
     6785     89/<- %esp 5/r32/ebp
     6786     5d/pop-to-ebp
     6787     c3/return
     6788
     6789 test-convert-index-into-array-of-bytes-using-offset-on-stack:
     6790     # . prologue
     6791     55/push-ebp
     6792     89/<- %ebp 4/r32/esp
     6793     # setup
     6794     (clear-stream _test-input-stream)
     6795     (clear-stream $_test-input-buffered-file->buffer)
     6796     (clear-stream _test-output-stream)
     6797     (clear-stream $_test-output-buffered-file->buffer)
     6798     #
     6799     (write _test-input-stream "fn foo {\n")
     6800     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6801     (write _test-input-stream "  var idx: int\n")
     6802     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6803     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6804     (write _test-input-stream "}\n")
     6805     # convert
     6806     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6807     (flush _test-output-buffered-file)
     6808 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6814     # check output
     6815     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
     6816     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
     6817     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
     6818     (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")
     6819     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
     6820     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
     6821     (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")
     6822     (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")
     6823     (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")
     6824     (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")
     6825     (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")
     6826     (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")
     6827     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
     6828     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
     6829     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
     6830     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
     6831     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
     6832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
     6833     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
     6834     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
     6835     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
     6836     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
     6837     # . epilogue
     6838     89/<- %esp 5/r32/ebp
     6839     5d/pop-to-ebp
     6840     c3/return
     6841
     6842 test-convert-function-and-type-definition:
     6843     # . prologue
     6844     55/push-ebp
     6845     89/<- %ebp 4/r32/esp
     6846     # setup
     6847     (clear-stream _test-input-stream)
     6848     (clear-stream $_test-input-buffered-file->buffer)
     6849     (clear-stream _test-output-stream)
     6850     (clear-stream $_test-output-buffered-file->buffer)
     6851     #
     6852     (write _test-input-stream "fn foo a: (addr t) {\n")
     6853     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
     6854     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
     6855     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
     6856     (write _test-input-stream "}\n")
     6857     (write _test-input-stream "type t {\n")
     6858     (write _test-input-stream "  x: int\n")
     6859     (write _test-input-stream "  y: int\n")
     6860     (write _test-input-stream "}\n")
     6861     # convert
     6862     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6863     (flush _test-output-buffered-file)
     6864 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6870     # check output
     6871     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
     6872     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
     6873     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
     6874     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
     6875     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
     6876     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
     6877     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
     6878     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
     6879     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
     6880     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
     6881     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
     6882     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
     6883     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
     6884     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
     6885     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
     6886     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
     6887     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
     6888     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
     6889     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
     6890     # . epilogue
     6891     89/<- %esp 5/r32/ebp
     6892     5d/pop-to-ebp
     6893     c3/return
     6894
     6895 test-type-definition-with-array:
     6896     # . prologue
     6897     55/push-ebp
     6898     89/<- %ebp 4/r32/esp
     6899     # setup
     6900     (clear-stream _test-input-stream)
     6901     (clear-stream $_test-input-buffered-file->buffer)
     6902     (clear-stream _test-output-stream)
     6903     (clear-stream $_test-output-buffered-file->buffer)
     6904     (clear-stream _test-error-stream)
     6905     (clear-stream $_test-error-buffered-file->buffer)
     6906     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6907     68/push 0/imm32
     6908     68/push 0/imm32
     6909     89/<- %edx 4/r32/esp
     6910     (tailor-exit-descriptor %edx 0x10)
     6911     #
     6912     (write _test-input-stream "type t {\n")
     6913     (write _test-input-stream "  a: (array int 3)\n")
     6914     (write _test-input-stream "}\n")
     6915     # convert
     6916     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6917     # registers except esp clobbered at this point
     6918     # restore ed
     6919     89/<- %edx 4/r32/esp
     6920     (flush _test-output-buffered-file)
     6921     (flush _test-error-buffered-file)
     6922 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6928     # check output
     6929     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
     6930     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
     6931     # check that stop(1) was called
     6932     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
     6933     # don't restore from ebp
     6934     81 0/subop/add %esp 8/imm32
     6935     # . epilogue
     6936     5d/pop-to-ebp
     6937     c3/return
     6938
     6939 test-type-definition-with-addr:
     6940     # . prologue
     6941     55/push-ebp
     6942     89/<- %ebp 4/r32/esp
     6943     # setup
     6944     (clear-stream _test-input-stream)
     6945     (clear-stream $_test-input-buffered-file->buffer)
     6946     (clear-stream _test-output-stream)
     6947     (clear-stream $_test-output-buffered-file->buffer)
     6948     (clear-stream _test-error-stream)
     6949     (clear-stream $_test-error-buffered-file->buffer)
     6950     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6951     68/push 0/imm32
     6952     68/push 0/imm32
     6953     89/<- %edx 4/r32/esp
     6954     (tailor-exit-descriptor %edx 0x10)
     6955     #
     6956     (write _test-input-stream "type t {\n")
     6957     (write _test-input-stream "  a: (addr int)\n")
     6958     (write _test-input-stream "}\n")
     6959     # convert
     6960     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6961     # registers except esp clobbered at this point
     6962     # restore ed
     6963     89/<- %edx 4/r32/esp
     6964     (flush _test-output-buffered-file)
     6965     (flush _test-error-buffered-file)
     6966 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6972     # check output
     6973     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
     6974     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
     6975     # check that stop(1) was called
     6976     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
     6977     # don't restore from ebp
     6978     81 0/subop/add %esp 8/imm32
     6979     # . epilogue
     6980     5d/pop-to-ebp
     6981     c3/return
     6982
     6983 test-convert-function-with-local-var-with-user-defined-type:
     6984     # . prologue
     6985     55/push-ebp
     6986     89/<- %ebp 4/r32/esp
     6987     # setup
     6988     (clear-stream _test-input-stream)
     6989     (clear-stream $_test-input-buffered-file->buffer)
     6990     (clear-stream _test-output-stream)
     6991     (clear-stream $_test-output-buffered-file->buffer)
     6992     #
     6993     (write _test-input-stream "fn foo {\n")
     6994     (write _test-input-stream "  var a: t\n")
     6995     (write _test-input-stream "}\n")
     6996     (write _test-input-stream "type t {\n")
     6997     (write _test-input-stream "  x: int\n")
     6998     (write _test-input-stream "  y: int\n")
     6999     (write _test-input-stream "}\n")
     7000     # convert
     7001     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7002     (flush _test-output-buffered-file)
     7003 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7009     # check output
     7010     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
     7011     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
     7012     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
     7013     (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")
     7014     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
     7015     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
     7016     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
     7017     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
     7018     (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")
     7019     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
     7020     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
     7021     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
     7022     (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")
     7023     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
     7024     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
     7025     # . epilogue
     7026     89/<- %esp 5/r32/ebp
     7027     5d/pop-to-ebp
     7028     c3/return
     7029
     7030 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
     7031     # . prologue
     7032     55/push-ebp
     7033     89/<- %ebp 4/r32/esp
     7034     # setup
     7035     (clear-stream _test-input-stream)
     7036     (clear-stream $_test-input-buffered-file->buffer)
     7037     (clear-stream _test-output-stream)
     7038     (clear-stream $_test-output-buffered-file->buffer)
     7039     #
     7040     (write _test-input-stream "fn foo {\n")
     7041     (write _test-input-stream "  var a: t\n")
     7042     (write _test-input-stream "}\n")
     7043     (write _test-input-stream "type t {\n")
     7044     (write _test-input-stream "  x: s\n")
     7045     (write _test-input-stream "}\n")
     7046     (write _test-input-stream "type s {\n")
     7047     (write _test-input-stream "  z: int\n")
     7048     (write _test-input-stream "}\n")
     7049     # convert
     7050     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7051     (flush _test-output-buffered-file)
     7052 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7058     # check output
     7059     (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")
     7060     (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")
     7061     (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")
     7062     (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")
     7063     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
     7064     (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")
     7065     (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")
     7066     (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")
     7067     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
     7068     (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")
     7069     (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")
     7070     (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")
     7071     (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")
     7072     (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")
     7073     # . epilogue
     7074     89/<- %esp 5/r32/ebp
     7075     5d/pop-to-ebp
     7076     c3/return
     7077
     7078 test-convert-function-call-with-arg-of-user-defined-type:
     7079     # . prologue
     7080     55/push-ebp
     7081     89/<- %ebp 4/r32/esp
     7082     # setup
     7083     (clear-stream _test-input-stream)
     7084     (clear-stream $_test-input-buffered-file->buffer)
     7085     (clear-stream _test-output-stream)
     7086     (clear-stream $_test-output-buffered-file->buffer)
     7087     #
     7088     (write _test-input-stream "fn f {\n")
     7089     (write _test-input-stream "  var a: t\n")
     7090     (write _test-input-stream "  foo a\n")
     7091     (write _test-input-stream "}\n")
     7092     (write _test-input-stream "fn foo x: t {\n")
     7093     (write _test-input-stream "}\n")
     7094     (write _test-input-stream "type t {\n")
     7095     (write _test-input-stream "  x: int\n")
     7096     (write _test-input-stream "  y: int\n")
     7097     (write _test-input-stream "}\n")
     7098     # convert
     7099     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7100     (flush _test-output-buffered-file)
     7101 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7107     # check output
     7108     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7109     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7110     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7111     (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")
     7112     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7113     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7114     # var a: t
     7115     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
     7116     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
     7117     # foo a
     7118     (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")
     7119     #
     7120     (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")
     7121     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7122     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7123     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7124     (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")
     7125     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7126     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7127     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7128     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7129     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7130     (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")
     7131     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7132     (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")
     7133     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7134     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7135     # . epilogue
     7136     89/<- %esp 5/r32/ebp
     7137     5d/pop-to-ebp
     7138     c3/return
     7139
     7140 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
     7141     # . prologue
     7142     55/push-ebp
     7143     89/<- %ebp 4/r32/esp
     7144     # setup
     7145     (clear-stream _test-input-stream)
     7146     (clear-stream $_test-input-buffered-file->buffer)
     7147     (clear-stream _test-output-stream)
     7148     (clear-stream $_test-output-buffered-file->buffer)
     7149     #
     7150     (write _test-input-stream "fn f {\n")
     7151     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
     7152     (write _test-input-stream "  foo *a\n")
     7153     (write _test-input-stream "}\n")
     7154     (write _test-input-stream "fn foo x: t {\n")
     7155     (write _test-input-stream "}\n")
     7156     (write _test-input-stream "type t {\n")
     7157     (write _test-input-stream "  x: int\n")
     7158     (write _test-input-stream "  y: int\n")
     7159     (write _test-input-stream "}\n")
     7160     # convert
     7161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7162     (flush _test-output-buffered-file)
     7163 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7169     # check output
     7170     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7173     (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")
     7174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7175     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7176     # var a
     7177     (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")
     7178     (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")
     7179     # foo a
     7180     (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")
     7181     #
     7182     (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")
     7183     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7184     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7185     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7186     (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")
     7187     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7188     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7189     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7190     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7191     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7192     (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")
     7193     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7194     (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")
     7195     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7196     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7197     # . epilogue
     7198     89/<- %esp 5/r32/ebp
     7199     5d/pop-to-ebp
     7200     c3/return
     7201
     7202 # we don't have special support for call-by-reference; just explicitly create
     7203 # a new variable with the address of the arg
     7204 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
     7205     # . prologue
     7206     55/push-ebp
     7207     89/<- %ebp 4/r32/esp
     7208     # setup
     7209     (clear-stream _test-input-stream)
     7210     (clear-stream $_test-input-buffered-file->buffer)
     7211     (clear-stream _test-output-stream)
     7212     (clear-stream $_test-output-buffered-file->buffer)
     7213     #
     7214     (write _test-input-stream "fn f {\n")
     7215     (write _test-input-stream "  var a: t\n")
     7216     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
     7217     (write _test-input-stream "  foo b\n")
     7218     (write _test-input-stream "}\n")
     7219     (write _test-input-stream "fn foo x: (addr t) {\n")
     7220     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
     7221     (write _test-input-stream "}\n")
     7222     (write _test-input-stream "type t {\n")
     7223     (write _test-input-stream "  x: int\n")
     7224     (write _test-input-stream "  y: int\n")
     7225     (write _test-input-stream "}\n")
     7226     # convert
     7227     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7228     (flush _test-output-buffered-file)
     7229 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7235     # check output
     7236     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
     7237     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
     7238     (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")
     7239     (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")
     7240     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
     7241     (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")
     7242     # var a: t
     7243     (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")
     7244     (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")
     7245     # var b/eax: (addr t)
     7246     (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")
     7247     (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")
     7248     # foo a
     7249     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
     7250     #
     7251     (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")
     7252     (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")
     7253     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
     7254     (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")
     7255     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
     7256     (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")
     7257     (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")
     7258     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
     7259     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
     7260     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
     7261     (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")
     7262     (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")
     7263     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
     7264     (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")
     7265     (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")
     7266     (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")
     7267     (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")
     7268     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
     7269     (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")
     7270     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
     7271     (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")
     7272     (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")
     7273     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
     7274     # . epilogue
     7275     89/<- %esp 5/r32/ebp
     7276     5d/pop-to-ebp
     7277     c3/return
     7278
     7279 test-convert-get-on-local-variable:
     7280     # . prologue
     7281     55/push-ebp
     7282     89/<- %ebp 4/r32/esp
     7283     # setup
     7284     (clear-stream _test-input-stream)
     7285     (clear-stream $_test-input-buffered-file->buffer)
     7286     (clear-stream _test-output-stream)
     7287     (clear-stream $_test-output-buffered-file->buffer)
     7288     #
     7289     (write _test-input-stream "fn foo {\n")
     7290     (write _test-input-stream "  var a: t\n")
     7291     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7292     (write _test-input-stream "}\n")
     7293     (write _test-input-stream "type t {\n")
     7294     (write _test-input-stream "  x: int\n")
     7295     (write _test-input-stream "  y: int\n")
     7296     (write _test-input-stream "}\n")
     7297     # convert
     7298     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7299     (flush _test-output-buffered-file)
     7300 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7306     # check output
     7307     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
     7308     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
     7309     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
     7310     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
     7311     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
     7312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
     7313     # var a
     7314     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
     7315     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
     7316     # var c
     7317     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
     7318     # get
     7319     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
     7320     # reclaim c
     7321     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
     7322     # reclaim a
     7323     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
     7324     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
     7325     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
     7326     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
     7327     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
     7328     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
     7329     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
     7330     # . epilogue
     7331     89/<- %esp 5/r32/ebp
     7332     5d/pop-to-ebp
     7333     c3/return
     7334
     7335 test-convert-get-on-function-argument:
     7336     # . prologue
     7337     55/push-ebp
     7338     89/<- %ebp 4/r32/esp
     7339     # setup
     7340     (clear-stream _test-input-stream)
     7341     (clear-stream $_test-input-buffered-file->buffer)
     7342     (clear-stream _test-output-stream)
     7343     (clear-stream $_test-output-buffered-file->buffer)
     7344     #
     7345     (write _test-input-stream "fn foo a: t {\n")
     7346     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7347     (write _test-input-stream "}\n")
     7348     (write _test-input-stream "type t {\n")
     7349     (write _test-input-stream "  x: int\n")
     7350     (write _test-input-stream "  y: int\n")
     7351     (write _test-input-stream "}\n")
     7352     # convert
     7353     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7354     (flush _test-output-buffered-file)
     7355 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7361     # check output
     7362     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
     7363     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
     7364     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
     7365     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
     7366     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
     7367     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
     7368     # var c
     7369     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
     7370     # get
     7371     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
     7372     # reclaim c
     7373     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
     7374     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
     7375     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
     7376     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
     7377     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
     7378     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
     7379     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
     7380     # . epilogue
     7381     89/<- %esp 5/r32/ebp
     7382     5d/pop-to-ebp
     7383     c3/return
     7384
     7385 test-convert-get-on-function-argument-with-known-type:
     7386     # . prologue
     7387     55/push-ebp
     7388     89/<- %ebp 4/r32/esp
     7389     # setup
     7390     (clear-stream _test-input-stream)
     7391     (clear-stream $_test-input-buffered-file->buffer)
     7392     (clear-stream _test-output-stream)
     7393     (clear-stream $_test-output-buffered-file->buffer)
     7394     #
     7395     (write _test-input-stream "type t {\n")
     7396     (write _test-input-stream "  x: int\n")
     7397     (write _test-input-stream "  y: int\n")
     7398     (write _test-input-stream "}\n")
     7399     (write _test-input-stream "fn foo a: t {\n")
     7400     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7401     (write _test-input-stream "}\n")
     7402     # convert
     7403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7404     (flush _test-output-buffered-file)
     7405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7411     # check output
     7412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
     7413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
     7414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
     7415     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
     7416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
     7417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
     7418     # var c
     7419     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
     7420     # get
     7421     (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")
     7422     # reclaim c
     7423     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
     7424     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
     7425     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
     7426     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
     7427     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
     7428     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
     7429     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
     7430     # . epilogue
     7431     89/<- %esp 5/r32/ebp
     7432     5d/pop-to-ebp
     7433     c3/return
     7434
     7435 test-add-with-too-many-inouts:
     7436     # . prologue
     7437     55/push-ebp
     7438     89/<- %ebp 4/r32/esp
     7439     # setup
     7440     (clear-stream _test-input-stream)
     7441     (clear-stream $_test-input-buffered-file->buffer)
     7442     (clear-stream _test-output-stream)
     7443     (clear-stream $_test-output-buffered-file->buffer)
     7444     (clear-stream _test-error-stream)
     7445     (clear-stream $_test-error-buffered-file->buffer)
     7446     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7447     68/push 0/imm32
     7448     68/push 0/imm32
     7449     89/<- %edx 4/r32/esp
     7450     (tailor-exit-descriptor %edx 0x10)
     7451     #
     7452     (write _test-input-stream "fn foo {\n")
     7453     (write _test-input-stream "  var a: int\n")
     7454     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
     7455     (write _test-input-stream "}\n")
     7456     # convert
     7457     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7458     # registers except esp clobbered at this point
     7459     # restore ed
     7460     89/<- %edx 4/r32/esp
     7461     (flush _test-output-buffered-file)
     7462     (flush _test-error-buffered-file)
     7463 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7469     # check output
     7470     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
     7471     (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")
     7472     # check that stop(1) was called
     7473     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
     7474     # don't restore from ebp
     7475     81 0/subop/add %esp 8/imm32
     7476     # . epilogue
     7477     5d/pop-to-ebp
     7478     c3/return
     7479
     7480 test-add-with-too-many-inouts-2:
     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 "  add-to a, 0, 1\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-2: output should be empty")
     7516     (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")
     7517     # check that stop(1) was called
     7518     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: 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-outputs:
     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/eax: int <- copy 0\n")
     7544     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
     7545     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
     7546     (write _test-input-stream "  c, b <- add a\n")
     7547     (write _test-input-stream "}\n")
     7548     # convert
     7549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7550     # registers except esp clobbered at this point
     7551     # restore ed
     7552     89/<- %edx 4/r32/esp
     7553     (flush _test-output-buffered-file)
     7554     (flush _test-error-buffered-file)
     7555 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7561     # check output
     7562     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
     7563     (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")
     7564     # check that stop(1) was called
     7565     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
     7566     # don't restore from ebp
     7567     81 0/subop/add %esp 8/imm32
     7568     # . epilogue
     7569     5d/pop-to-ebp
     7570     c3/return
     7571
     7572 test-add-with-non-number:
     7573     # . prologue
     7574     55/push-ebp
     7575     89/<- %ebp 4/r32/esp
     7576     # setup
     7577     (clear-stream _test-input-stream)
     7578     (clear-stream $_test-input-buffered-file->buffer)
     7579     (clear-stream _test-output-stream)
     7580     (clear-stream $_test-output-buffered-file->buffer)
     7581     (clear-stream _test-error-stream)
     7582     (clear-stream $_test-error-buffered-file->buffer)
     7583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7584     68/push 0/imm32
     7585     68/push 0/imm32
     7586     89/<- %edx 4/r32/esp
     7587     (tailor-exit-descriptor %edx 0x10)
     7588     #
     7589     (write _test-input-stream "fn foo {\n")
     7590     (write _test-input-stream "  var a: int\n")
     7591     (write _test-input-stream "  var b/ecx: (addr int) <- 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-non-number: output should be empty")
     7608     (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")
     7609     # check that stop(1) was called
     7610     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: 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-addr-dereferenced:
     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     #
     7627     (write _test-input-stream "fn foo {\n")
     7628     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
     7629     (write _test-input-stream "  add-to *a, 1\n")
     7630     (write _test-input-stream "}\n")
     7631     # convert
     7632     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7633     (flush _test-output-buffered-file)
     7634     # no error
     7635     # . epilogue
     7636     89/<- %esp 5/r32/ebp
     7637     5d/pop-to-ebp
     7638     c3/return
     7639
     7640 test-copy-with-no-inout:
     7641     # . prologue
     7642     55/push-ebp
     7643     89/<- %ebp 4/r32/esp
     7644     # setup
     7645     (clear-stream _test-input-stream)
     7646     (clear-stream $_test-input-buffered-file->buffer)
     7647     (clear-stream _test-output-stream)
     7648     (clear-stream $_test-output-buffered-file->buffer)
     7649     (clear-stream _test-error-stream)
     7650     (clear-stream $_test-error-buffered-file->buffer)
     7651     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7652     68/push 0/imm32
     7653     68/push 0/imm32
     7654     89/<- %edx 4/r32/esp
     7655     (tailor-exit-descriptor %edx 0x10)
     7656     #
     7657     (write _test-input-stream "fn foo {\n")
     7658     (write _test-input-stream "  var x/eax: boolean <- copy\n")
     7659     (write _test-input-stream "}\n")
     7660     # convert
     7661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7662     # registers except esp clobbered at this point
     7663     # restore ed
     7664     89/<- %edx 4/r32/esp
     7665     (flush _test-output-buffered-file)
     7666     (flush _test-error-buffered-file)
     7667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7673     # check output
     7674     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
     7675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
     7676     # check that stop(1) was called
     7677     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
     7678     # don't restore from ebp
     7679     81 0/subop/add %esp 8/imm32
     7680     # . epilogue
     7681     5d/pop-to-ebp
     7682     c3/return
     7683
     7684 test-copy-with-multiple-inouts:
     7685     # . prologue
     7686     55/push-ebp
     7687     89/<- %ebp 4/r32/esp
     7688     # setup
     7689     (clear-stream _test-input-stream)
     7690     (clear-stream $_test-input-buffered-file->buffer)
     7691     (clear-stream _test-output-stream)
     7692     (clear-stream $_test-output-buffered-file->buffer)
     7693     (clear-stream _test-error-stream)
     7694     (clear-stream $_test-error-buffered-file->buffer)
     7695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7696     68/push 0/imm32
     7697     68/push 0/imm32
     7698     89/<- %edx 4/r32/esp
     7699     (tailor-exit-descriptor %edx 0x10)
     7700     #
     7701     (write _test-input-stream "fn foo {\n")
     7702     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
     7703     (write _test-input-stream "}\n")
     7704     # convert
     7705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7706     # registers except esp clobbered at this point
     7707     # restore ed
     7708     89/<- %edx 4/r32/esp
     7709     (flush _test-output-buffered-file)
     7710     (flush _test-error-buffered-file)
     7711 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7717     # check output
     7718     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
     7719     (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")
     7720     # check that stop(1) was called
     7721     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
     7722     # don't restore from ebp
     7723     81 0/subop/add %esp 8/imm32
     7724     # . epilogue
     7725     5d/pop-to-ebp
     7726     c3/return
     7727
     7728 test-copy-with-no-output:
     7729     # . prologue
     7730     55/push-ebp
     7731     89/<- %ebp 4/r32/esp
     7732     # setup
     7733     (clear-stream _test-input-stream)
     7734     (clear-stream $_test-input-buffered-file->buffer)
     7735     (clear-stream _test-output-stream)
     7736     (clear-stream $_test-output-buffered-file->buffer)
     7737     (clear-stream _test-error-stream)
     7738     (clear-stream $_test-error-buffered-file->buffer)
     7739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7740     68/push 0/imm32
     7741     68/push 0/imm32
     7742     89/<- %edx 4/r32/esp
     7743     (tailor-exit-descriptor %edx 0x10)
     7744     #
     7745     (write _test-input-stream "fn foo {\n")
     7746     (write _test-input-stream "  copy 0\n")
     7747     (write _test-input-stream "}\n")
     7748     # convert
     7749     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7750     # registers except esp clobbered at this point
     7751     # restore ed
     7752     89/<- %edx 4/r32/esp
     7753     (flush _test-output-buffered-file)
     7754     (flush _test-error-buffered-file)
     7755 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7761     # check output
     7762     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
     7763     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
     7764     # check that stop(1) was called
     7765     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
     7766     # don't restore from ebp
     7767     81 0/subop/add %esp 8/imm32
     7768     # . epilogue
     7769     5d/pop-to-ebp
     7770     c3/return
     7771
     7772 test-copy-with-multiple-outputs:
     7773     # . prologue
     7774     55/push-ebp
     7775     89/<- %ebp 4/r32/esp
     7776     # setup
     7777     (clear-stream _test-input-stream)
     7778     (clear-stream $_test-input-buffered-file->buffer)
     7779     (clear-stream _test-output-stream)
     7780     (clear-stream $_test-output-buffered-file->buffer)
     7781     (clear-stream _test-error-stream)
     7782     (clear-stream $_test-error-buffered-file->buffer)
     7783     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7784     68/push 0/imm32
     7785     68/push 0/imm32
     7786     89/<- %edx 4/r32/esp
     7787     (tailor-exit-descriptor %edx 0x10)
     7788     #
     7789     (write _test-input-stream "fn foo {\n")
     7790     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     7791     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     7792     (write _test-input-stream "  x, y <- copy 0\n")
     7793     (write _test-input-stream "}\n")
     7794     # convert
     7795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7796     # registers except esp clobbered at this point
     7797     # restore ed
     7798     89/<- %edx 4/r32/esp
     7799     (flush _test-output-buffered-file)
     7800     (flush _test-error-buffered-file)
     7801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7807     # check output
     7808     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
     7809     (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")
     7810     # check that stop(1) was called
     7811     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
     7812     # don't restore from ebp
     7813     81 0/subop/add %esp 8/imm32
     7814     # . epilogue
     7815     5d/pop-to-ebp
     7816     c3/return
     7817
     7818 test-copy-invalid-value-to-address:
     7819     # . prologue
     7820     55/push-ebp
     7821     89/<- %ebp 4/r32/esp
     7822     # setup
     7823     (clear-stream _test-input-stream)
     7824     (clear-stream $_test-input-buffered-file->buffer)
     7825     (clear-stream _test-output-stream)
     7826     (clear-stream $_test-output-buffered-file->buffer)
     7827     (clear-stream _test-error-stream)
     7828     (clear-stream $_test-error-buffered-file->buffer)
     7829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7830     68/push 0/imm32
     7831     68/push 0/imm32
     7832     89/<- %edx 4/r32/esp
     7833     (tailor-exit-descriptor %edx 0x10)
     7834     #
     7835     (write _test-input-stream "fn foo {\n")
     7836     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7837     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\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-invalid-value-to-address: output should be empty")
     7854     (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")
     7855     # check that stop(1) was called
     7856     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: 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-null-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     #
     7873     (write _test-input-stream "fn foo {\n")
     7874     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     7875     (write _test-input-stream "}\n")
     7876     # convert
     7877     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7878     (flush _test-output-buffered-file)
     7879     # no errors
     7880     # . epilogue
     7881     89/<- %esp 5/r32/ebp
     7882     5d/pop-to-ebp
     7883     c3/return
     7884
     7885 test-copy-invalid-value-to-offset:
     7886     # . prologue
     7887     55/push-ebp
     7888     89/<- %ebp 4/r32/esp
     7889     # setup
     7890     (clear-stream _test-input-stream)
     7891     (clear-stream $_test-input-buffered-file->buffer)
     7892     (clear-stream _test-output-stream)
     7893     (clear-stream $_test-output-buffered-file->buffer)
     7894     (clear-stream _test-error-stream)
     7895     (clear-stream $_test-error-buffered-file->buffer)
     7896     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7897     68/push 0/imm32
     7898     68/push 0/imm32
     7899     89/<- %edx 4/r32/esp
     7900     (tailor-exit-descriptor %edx 0x10)
     7901     #
     7902     (write _test-input-stream "fn foo {\n")
     7903     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7904     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
     7905     (write _test-input-stream "}\n")
     7906     # convert
     7907     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7908     # registers except esp clobbered at this point
     7909     # restore ed
     7910     89/<- %edx 4/r32/esp
     7911     (flush _test-output-buffered-file)
     7912     (flush _test-error-buffered-file)
     7913 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7919     # check output
     7920     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7921     (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")
     7922     # check that stop(1) was called
     7923     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
     7924     # don't restore from ebp
     7925     81 0/subop/add %esp 8/imm32
     7926     # . epilogue
     7927     5d/pop-to-ebp
     7928     c3/return
     7929
     7930 test-copy-null-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     #
     7940     (write _test-input-stream "fn foo {\n")
     7941     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
     7942     (write _test-input-stream "}\n")
     7943     # convert
     7944     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7945     (flush _test-output-buffered-file)
     7946 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7952     # no errors
     7953     # . epilogue
     7954     89/<- %esp 5/r32/ebp
     7955     5d/pop-to-ebp
     7956     c3/return
     7957
     7958 test-copy-non-literal-to-byte:
     7959     # . prologue
     7960     55/push-ebp
     7961     89/<- %ebp 4/r32/esp
     7962     # setup
     7963     (clear-stream _test-input-stream)
     7964     (clear-stream $_test-input-buffered-file->buffer)
     7965     (clear-stream _test-output-stream)
     7966     (clear-stream $_test-output-buffered-file->buffer)
     7967     (clear-stream _test-error-stream)
     7968     (clear-stream $_test-error-buffered-file->buffer)
     7969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7970     68/push 0/imm32
     7971     68/push 0/imm32
     7972     89/<- %edx 4/r32/esp
     7973     (tailor-exit-descriptor %edx 0x10)
     7974     #
     7975     (write _test-input-stream "fn foo {\n")
     7976     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     7977     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
     7978     (write _test-input-stream "}\n")
     7979     # convert
     7980     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7981     # registers except esp clobbered at this point
     7982     # restore ed
     7983     89/<- %edx 4/r32/esp
     7984     (flush _test-output-buffered-file)
     7985     (flush _test-error-buffered-file)
     7986 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7992     # check output
     7993     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
     7994     (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")
     7995     # check that stop(1) was called
     7996     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
     7997     # don't restore from ebp
     7998     81 0/subop/add %esp 8/imm32
     7999     # . epilogue
     8000     5d/pop-to-ebp
     8001     c3/return
     8002
     8003 test-copy-deref-address:
     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     #
     8013     (write _test-input-stream "fn foo {\n")
     8014     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
     8015     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
     8016     (write _test-input-stream "}\n")
     8017     # convert
     8018     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8019     (flush _test-output-buffered-file)
     8020     # no errors
     8021     # . epilogue
     8022     5d/pop-to-ebp
     8023     c3/return
     8024
     8025 test-copy-to-non-register:
     8026     # . prologue
     8027     55/push-ebp
     8028     89/<- %ebp 4/r32/esp
     8029     # setup
     8030     (clear-stream _test-input-stream)
     8031     (clear-stream $_test-input-buffered-file->buffer)
     8032     (clear-stream _test-output-stream)
     8033     (clear-stream $_test-output-buffered-file->buffer)
     8034     (clear-stream _test-error-stream)
     8035     (clear-stream $_test-error-buffered-file->buffer)
     8036     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8037     68/push 0/imm32
     8038     68/push 0/imm32
     8039     89/<- %edx 4/r32/esp
     8040     (tailor-exit-descriptor %edx 0x10)
     8041     #
     8042     (write _test-input-stream "fn foo {\n")
     8043     (write _test-input-stream "  var x: int\n")
     8044     (write _test-input-stream "  x <- copy 0\n")
     8045     (write _test-input-stream "}\n")
     8046     # convert
     8047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8048     # registers except esp clobbered at this point
     8049     # restore ed
     8050     89/<- %edx 4/r32/esp
     8051     (flush _test-output-buffered-file)
     8052     (flush _test-error-buffered-file)
     8053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8059     # check output
     8060     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
     8061     (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")
     8062     # check that stop(1) was called
     8063     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
     8064     # don't restore from ebp
     8065     81 0/subop/add %esp 8/imm32
     8066     # . epilogue
     8067     5d/pop-to-ebp
     8068     c3/return
     8069
     8070 test-copy-from-non-scalar-inout:
     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: (handle int)\n")
     8089     (write _test-input-stream "  var y/eax: int <- copy x\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-from-non-scalar-inout: output should be empty")
     8106     (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")
     8107     # check that stop(1) was called
     8108     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: 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-to-with-no-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 "  copy-to\n")
     8134     (write _test-input-stream "}\n")
     8135     # convert
     8136     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8137     # registers except esp clobbered at this point
     8138     # restore ed
     8139     89/<- %edx 4/r32/esp
     8140     (flush _test-output-buffered-file)
     8141     (flush _test-error-buffered-file)
     8142 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8148     # check output
     8149     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
     8150     (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")
     8151     # check that stop(1) was called
     8152     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
     8153     # don't restore from ebp
     8154     81 0/subop/add %esp 8/imm32
     8155     # . epilogue
     8156     5d/pop-to-ebp
     8157     c3/return
     8158
     8159 test-copy-to-with-no-source:
     8160     # . prologue
     8161     55/push-ebp
     8162     89/<- %ebp 4/r32/esp
     8163     # setup
     8164     (clear-stream _test-input-stream)
     8165     (clear-stream $_test-input-buffered-file->buffer)
     8166     (clear-stream _test-output-stream)
     8167     (clear-stream $_test-output-buffered-file->buffer)
     8168     (clear-stream _test-error-stream)
     8169     (clear-stream $_test-error-buffered-file->buffer)
     8170     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8171     68/push 0/imm32
     8172     68/push 0/imm32
     8173     89/<- %edx 4/r32/esp
     8174     (tailor-exit-descriptor %edx 0x10)
     8175     #
     8176     (write _test-input-stream "fn foo {\n")
     8177     (write _test-input-stream "  var x: boolean\n")
     8178     (write _test-input-stream "  copy-to x\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-source: 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-source: error message")
     8196     # check that stop(1) was called
     8197     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: 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-register:
     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, 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-register: output should be empty")
     8240     (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")
     8241     # check that stop(1) was called
     8242     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: 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-too-many-inouts:
     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, 0, 0\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-too-many-inouts: output should be empty")
     8285     (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")
     8286     # check that stop(1) was called
     8287     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: 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-output:
     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/eax: boolean <- copy 0\n")
     8313     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     8314     (write _test-input-stream "  x <- copy-to y, 0\n")
     8315     (write _test-input-stream "}\n")
     8316     # convert
     8317     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8318     # registers except esp clobbered at this point
     8319     # restore ed
     8320     89/<- %edx 4/r32/esp
     8321     (flush _test-output-buffered-file)
     8322     (flush _test-error-buffered-file)
     8323 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8329     # check output
     8330     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
     8331     (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")
     8332     # check that stop(1) was called
     8333     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
     8334     # don't restore from ebp
     8335     81 0/subop/add %esp 8/imm32
     8336     # . epilogue
     8337     5d/pop-to-ebp
     8338     c3/return
     8339
     8340 test-copy-to-invalid-value-to-address:
     8341     # . prologue
     8342     55/push-ebp
     8343     89/<- %ebp 4/r32/esp
     8344     # setup
     8345     (clear-stream _test-input-stream)
     8346     (clear-stream $_test-input-buffered-file->buffer)
     8347     (clear-stream _test-output-stream)
     8348     (clear-stream $_test-output-buffered-file->buffer)
     8349     (clear-stream _test-error-stream)
     8350     (clear-stream $_test-error-buffered-file->buffer)
     8351     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8352     68/push 0/imm32
     8353     68/push 0/imm32
     8354     89/<- %edx 4/r32/esp
     8355     (tailor-exit-descriptor %edx 0x10)
     8356     #
     8357     (write _test-input-stream "fn foo {\n")
     8358     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8359     (write _test-input-stream "  var y: (addr int)\n")
     8360     (write _test-input-stream "  copy-to y, x\n")
     8361     (write _test-input-stream "}\n")
     8362     # convert
     8363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8364     # registers except esp clobbered at this point
     8365     # restore ed
     8366     89/<- %edx 4/r32/esp
     8367     (flush _test-output-buffered-file)
     8368     (flush _test-error-buffered-file)
     8369 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8375     # check output
     8376     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
     8377     (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")
     8378     # check that stop(1) was called
     8379     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
     8380     # don't restore from ebp
     8381     81 0/subop/add %esp 8/imm32
     8382     # . epilogue
     8383     5d/pop-to-ebp
     8384     c3/return
     8385
     8386 test-copy-to-null-value-to-address:
     8387     # . prologue
     8388     55/push-ebp
     8389     89/<- %ebp 4/r32/esp
     8390     # setup
     8391     (clear-stream _test-input-stream)
     8392     (clear-stream $_test-input-buffered-file->buffer)
     8393     (clear-stream _test-output-stream)
     8394     (clear-stream $_test-output-buffered-file->buffer)
     8395     #
     8396     (write _test-input-stream "fn foo {\n")
     8397     (write _test-input-stream "  var y: (addr int)\n")
     8398     (write _test-input-stream "  copy-to y, 0\n")
     8399     (write _test-input-stream "}\n")
     8400     # convert
     8401     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8402     (flush _test-output-buffered-file)
     8403     # no errors
     8404     # . epilogue
     8405     89/<- %esp 5/r32/ebp
     8406     5d/pop-to-ebp
     8407     c3/return
     8408
     8409 test-copy-to-invalid-value-to-offset:
     8410     # . prologue
     8411     55/push-ebp
     8412     89/<- %ebp 4/r32/esp
     8413     # setup
     8414     (clear-stream _test-input-stream)
     8415     (clear-stream $_test-input-buffered-file->buffer)
     8416     (clear-stream _test-output-stream)
     8417     (clear-stream $_test-output-buffered-file->buffer)
     8418     (clear-stream _test-error-stream)
     8419     (clear-stream $_test-error-buffered-file->buffer)
     8420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8421     68/push 0/imm32
     8422     68/push 0/imm32
     8423     89/<- %edx 4/r32/esp
     8424     (tailor-exit-descriptor %edx 0x10)
     8425     #
     8426     (write _test-input-stream "fn foo {\n")
     8427     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8428     (write _test-input-stream "  var y: (offset int)\n")
     8429     (write _test-input-stream "  copy-to y, x\n")
     8430     (write _test-input-stream "}\n")
     8431     # convert
     8432     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8433     # registers except esp clobbered at this point
     8434     # restore ed
     8435     89/<- %edx 4/r32/esp
     8436     (flush _test-output-buffered-file)
     8437     (flush _test-error-buffered-file)
     8438 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8444     # check output
     8445     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
     8446     (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")
     8447     # check that stop(1) was called
     8448     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
     8449     # don't restore from ebp
     8450     81 0/subop/add %esp 8/imm32
     8451     # . epilogue
     8452     5d/pop-to-ebp
     8453     c3/return
     8454
     8455 test-copy-to-null-value-to-offset:
     8456     # . prologue
     8457     55/push-ebp
     8458     89/<- %ebp 4/r32/esp
     8459     # setup
     8460     (clear-stream _test-input-stream)
     8461     (clear-stream $_test-input-buffered-file->buffer)
     8462     (clear-stream _test-output-stream)
     8463     (clear-stream $_test-output-buffered-file->buffer)
     8464     #
     8465     (write _test-input-stream "fn foo {\n")
     8466     (write _test-input-stream "  var y: (offset int)\n")
     8467     (write _test-input-stream "  copy-to y, 0\n")
     8468     (write _test-input-stream "}\n")
     8469     # convert
     8470     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8471     (flush _test-output-buffered-file)
     8472     # no errors
     8473     # . epilogue
     8474     89/<- %esp 5/r32/ebp
     8475     5d/pop-to-ebp
     8476     c3/return
     8477
     8478 test-copy-to-non-literal-to-byte:
     8479     # . prologue
     8480     55/push-ebp
     8481     89/<- %ebp 4/r32/esp
     8482     # setup
     8483     (clear-stream _test-input-stream)
     8484     (clear-stream $_test-input-buffered-file->buffer)
     8485     (clear-stream _test-output-stream)
     8486     (clear-stream $_test-output-buffered-file->buffer)
     8487     (clear-stream _test-error-stream)
     8488     (clear-stream $_test-error-buffered-file->buffer)
     8489     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8490     68/push 0/imm32
     8491     68/push 0/imm32
     8492     89/<- %edx 4/r32/esp
     8493     (tailor-exit-descriptor %edx 0x10)
     8494     #
     8495     (write _test-input-stream "fn foo {\n")
     8496     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
     8497     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     8498     (write _test-input-stream "  copy-to *y, x\n")
     8499     (write _test-input-stream "}\n")
     8500     # convert
     8501     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8502     # registers except esp clobbered at this point
     8503     # restore ed
     8504     89/<- %edx 4/r32/esp
     8505     (flush _test-output-buffered-file)
     8506     (flush _test-error-buffered-file)
     8507 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8513     # check output
     8514     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
     8515     (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")
     8516     # check that stop(1) was called
     8517     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
     8518     # don't restore from ebp
     8519     81 0/subop/add %esp 8/imm32
     8520     # . epilogue
     8521     5d/pop-to-ebp
     8522     c3/return
     8523
     8524 test-copy-to-deref-address:
     8525     # . prologue
     8526     55/push-ebp
     8527     89/<- %ebp 4/r32/esp
     8528     # setup
     8529     (clear-stream _test-input-stream)
     8530     (clear-stream $_test-input-buffered-file->buffer)
     8531     (clear-stream _test-output-stream)
     8532     (clear-stream $_test-output-buffered-file->buffer)
     8533     #
     8534     (write _test-input-stream "fn foo {\n")
     8535     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     8536     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     8537     (write _test-input-stream "  copy-to *y, x\n")
     8538     (write _test-input-stream "}\n")
     8539     # convert
     8540     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8541     (flush _test-output-buffered-file)
     8542     # no errors
     8543     # . epilogue
     8544     5d/pop-to-ebp
     8545     c3/return
     8546
     8547 test-copy-to-from-non-scalar-inout:
     8548     # . prologue
     8549     55/push-ebp
     8550     89/<- %ebp 4/r32/esp
     8551     # setup
     8552     (clear-stream _test-input-stream)
     8553     (clear-stream $_test-input-buffered-file->buffer)
     8554     (clear-stream _test-output-stream)
     8555     (clear-stream $_test-output-buffered-file->buffer)
     8556     (clear-stream _test-error-stream)
     8557     (clear-stream $_test-error-buffered-file->buffer)
     8558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8559     68/push 0/imm32
     8560     68/push 0/imm32
     8561     89/<- %edx 4/r32/esp
     8562     (tailor-exit-descriptor %edx 0x10)
     8563     #
     8564     (write _test-input-stream "fn foo {\n")
     8565     (write _test-input-stream "  var x: (handle int)\n")
     8566     (write _test-input-stream "  var y: int\n")
     8567     (write _test-input-stream "  copy-to y, x\n")
     8568     (write _test-input-stream "}\n")
     8569     # convert
     8570     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8571     # registers except esp clobbered at this point
     8572     # restore ed
     8573     89/<- %edx 4/r32/esp
     8574     (flush _test-output-buffered-file)
     8575     (flush _test-error-buffered-file)
     8576 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8582     # check output
     8583     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
     8584     (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")
     8585     # check that stop(1) was called
     8586     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
     8587     # don't restore from ebp
     8588     81 0/subop/add %esp 8/imm32
     8589     # . epilogue
     8590     5d/pop-to-ebp
     8591     c3/return
     8592
     8593 test-copy-byte-with-no-inout:
     8594     # . prologue
     8595     55/push-ebp
     8596     89/<- %ebp 4/r32/esp
     8597     # setup
     8598     (clear-stream _test-input-stream)
     8599     (clear-stream $_test-input-buffered-file->buffer)
     8600     (clear-stream _test-output-stream)
     8601     (clear-stream $_test-output-buffered-file->buffer)
     8602     (clear-stream _test-error-stream)
     8603     (clear-stream $_test-error-buffered-file->buffer)
     8604     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8605     68/push 0/imm32
     8606     68/push 0/imm32
     8607     89/<- %edx 4/r32/esp
     8608     (tailor-exit-descriptor %edx 0x10)
     8609     #
     8610     (write _test-input-stream "fn foo {\n")
     8611     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
     8612     (write _test-input-stream "}\n")
     8613     # convert
     8614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8615     # registers except esp clobbered at this point
     8616     # restore ed
     8617     89/<- %edx 4/r32/esp
     8618     (flush _test-output-buffered-file)
     8619     (flush _test-error-buffered-file)
     8620 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8626     # check output
     8627     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
     8628     (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")
     8629     # check that stop(1) was called
     8630     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
     8631     # don't restore from ebp
     8632     81 0/subop/add %esp 8/imm32
     8633     # . epilogue
     8634     5d/pop-to-ebp
     8635     c3/return
     8636
     8637 test-copy-byte-with-multiple-inouts:
     8638     # . prologue
     8639     55/push-ebp
     8640     89/<- %ebp 4/r32/esp
     8641     # setup
     8642     (clear-stream _test-input-stream)
     8643     (clear-stream $_test-input-buffered-file->buffer)
     8644     (clear-stream _test-output-stream)
     8645     (clear-stream $_test-output-buffered-file->buffer)
     8646     (clear-stream _test-error-stream)
     8647     (clear-stream $_test-error-buffered-file->buffer)
     8648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8649     68/push 0/imm32
     8650     68/push 0/imm32
     8651     89/<- %edx 4/r32/esp
     8652     (tailor-exit-descriptor %edx 0x10)
     8653     #
     8654     (write _test-input-stream "fn foo {\n")
     8655     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
     8656     (write _test-input-stream "}\n")
     8657     # convert
     8658     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8659     # registers except esp clobbered at this point
     8660     # restore ed
     8661     89/<- %edx 4/r32/esp
     8662     (flush _test-output-buffered-file)
     8663     (flush _test-error-buffered-file)
     8664 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8670     # check output
     8671     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
     8672     (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")
     8673     # check that stop(1) was called
     8674     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
     8675     # don't restore from ebp
     8676     81 0/subop/add %esp 8/imm32
     8677     # . epilogue
     8678     5d/pop-to-ebp
     8679     c3/return
     8680
     8681 test-copy-byte-with-no-output:
     8682     # . prologue
     8683     55/push-ebp
     8684     89/<- %ebp 4/r32/esp
     8685     # setup
     8686     (clear-stream _test-input-stream)
     8687     (clear-stream $_test-input-buffered-file->buffer)
     8688     (clear-stream _test-output-stream)
     8689     (clear-stream $_test-output-buffered-file->buffer)
     8690     (clear-stream _test-error-stream)
     8691     (clear-stream $_test-error-buffered-file->buffer)
     8692     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8693     68/push 0/imm32
     8694     68/push 0/imm32
     8695     89/<- %edx 4/r32/esp
     8696     (tailor-exit-descriptor %edx 0x10)
     8697     #
     8698     (write _test-input-stream "fn foo {\n")
     8699     (write _test-input-stream "  copy-byte 0\n")
     8700     (write _test-input-stream "}\n")
     8701     # convert
     8702     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8703     # registers except esp clobbered at this point
     8704     # restore ed
     8705     89/<- %edx 4/r32/esp
     8706     (flush _test-output-buffered-file)
     8707     (flush _test-error-buffered-file)
     8708 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8714     # check output
     8715     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
     8716     (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")
     8717     # check that stop(1) was called
     8718     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
     8719     # don't restore from ebp
     8720     81 0/subop/add %esp 8/imm32
     8721     # . epilogue
     8722     5d/pop-to-ebp
     8723     c3/return
     8724
     8725 test-copy-byte-with-multiple-outputs:
     8726     # . prologue
     8727     55/push-ebp
     8728     89/<- %ebp 4/r32/esp
     8729     # setup
     8730     (clear-stream _test-input-stream)
     8731     (clear-stream $_test-input-buffered-file->buffer)
     8732     (clear-stream _test-output-stream)
     8733     (clear-stream $_test-output-buffered-file->buffer)
     8734     (clear-stream _test-error-stream)
     8735     (clear-stream $_test-error-buffered-file->buffer)
     8736     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8737     68/push 0/imm32
     8738     68/push 0/imm32
     8739     89/<- %edx 4/r32/esp
     8740     (tailor-exit-descriptor %edx 0x10)
     8741     #
     8742     (write _test-input-stream "fn foo {\n")
     8743     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     8744     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     8745     (write _test-input-stream "  x, y <- copy-byte 0\n")
     8746     (write _test-input-stream "}\n")
     8747     # convert
     8748     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8749     # registers except esp clobbered at this point
     8750     # restore ed
     8751     89/<- %edx 4/r32/esp
     8752     (flush _test-output-buffered-file)
     8753     (flush _test-error-buffered-file)
     8754 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8760     # check output
     8761     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
     8762     (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")
     8763     # check that stop(1) was called
     8764     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
     8765     # don't restore from ebp
     8766     81 0/subop/add %esp 8/imm32
     8767     # . epilogue
     8768     5d/pop-to-ebp
     8769     c3/return
     8770
     8771 test-copy-byte-deref-address:
     8772     # . prologue
     8773     55/push-ebp
     8774     89/<- %ebp 4/r32/esp
     8775     # setup
     8776     (clear-stream _test-input-stream)
     8777     (clear-stream $_test-input-buffered-file->buffer)
     8778     (clear-stream _test-output-stream)
     8779     (clear-stream $_test-output-buffered-file->buffer)
     8780     #
     8781     (write _test-input-stream "fn foo {\n")
     8782     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8783     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
     8784     (write _test-input-stream "}\n")
     8785     # convert
     8786     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8787     (flush _test-output-buffered-file)
     8788 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8794     # not bothering checking output
     8795     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
     8796     # . epilogue
     8797     5d/pop-to-ebp
     8798     c3/return
     8799
     8800 test-copy-byte-with-invalid-output-type:
     8801     # . prologue
     8802     55/push-ebp
     8803     89/<- %ebp 4/r32/esp
     8804     # setup
     8805     (clear-stream _test-input-stream)
     8806     (clear-stream $_test-input-buffered-file->buffer)
     8807     (clear-stream _test-output-stream)
     8808     (clear-stream $_test-output-buffered-file->buffer)
     8809     (clear-stream _test-error-stream)
     8810     (clear-stream $_test-error-buffered-file->buffer)
     8811     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8812     68/push 0/imm32
     8813     68/push 0/imm32
     8814     89/<- %edx 4/r32/esp
     8815     (tailor-exit-descriptor %edx 0x10)
     8816     #
     8817     (write _test-input-stream "fn foo {\n")
     8818     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8819     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
     8820     (write _test-input-stream "}\n")
     8821     # convert
     8822     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8823     # registers except esp clobbered at this point
     8824     # restore ed
     8825     89/<- %edx 4/r32/esp
     8826     (flush _test-output-buffered-file)
     8827     (flush _test-error-buffered-file)
     8828 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8834     # check output
     8835     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
     8836     (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")
     8837     # check that stop(1) was called
     8838     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
     8839     # don't restore from ebp
     8840     81 0/subop/add %esp 8/imm32
     8841     # . epilogue
     8842     5d/pop-to-ebp
     8843     c3/return
     8844
     8845 test-copy-byte-from-non-scalar-inout:
     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: (handle int)\n")
     8864     (write _test-input-stream "  var y/eax: byte <- 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-from-non-scalar-inout: output should be empty")
     8881     (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")
     8882     # check that stop(1) was called
     8883     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: 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-to-with-no-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 "  copy-byte-to\n")
     8909     (write _test-input-stream "}\n")
     8910     # convert
     8911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8912     # registers except esp clobbered at this point
     8913     # restore ed
     8914     89/<- %edx 4/r32/esp
     8915     (flush _test-output-buffered-file)
     8916     (flush _test-error-buffered-file)
     8917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8923     # check output
     8924     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
     8925     (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")
     8926     # check that stop(1) was called
     8927     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
     8928     # don't restore from ebp
     8929     81 0/subop/add %esp 8/imm32
     8930     # . epilogue
     8931     5d/pop-to-ebp
     8932     c3/return
     8933
     8934 test-copy-byte-to-with-no-source:
     8935     # . prologue
     8936     55/push-ebp
     8937     89/<- %ebp 4/r32/esp
     8938     # setup
     8939     (clear-stream _test-input-stream)
     8940     (clear-stream $_test-input-buffered-file->buffer)
     8941     (clear-stream _test-output-stream)
     8942     (clear-stream $_test-output-buffered-file->buffer)
     8943     (clear-stream _test-error-stream)
     8944     (clear-stream $_test-error-buffered-file->buffer)
     8945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8946     68/push 0/imm32
     8947     68/push 0/imm32
     8948     89/<- %edx 4/r32/esp
     8949     (tailor-exit-descriptor %edx 0x10)
     8950     #
     8951     (write _test-input-stream "fn foo {\n")
     8952     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8953     (write _test-input-stream "  copy-byte-to *x\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-source: 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-source: error message")
     8971     # check that stop(1) was called
     8972     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: 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-too-many-inouts:
     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, 0, 0\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-too-many-inouts: 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-too-many-inouts: error message")
     9016     # check that stop(1) was called
     9017     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: 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-output:
     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: byte <- copy 0\n")
     9043     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9044     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
     9045     (write _test-input-stream "}\n")
     9046     # convert
     9047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9048     # registers except esp clobbered at this point
     9049     # restore ed
     9050     89/<- %edx 4/r32/esp
     9051     (flush _test-output-buffered-file)
     9052     (flush _test-error-buffered-file)
     9053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9059     # check output
     9060     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
     9061     (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")
     9062     # check that stop(1) was called
     9063     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
     9064     # don't restore from ebp
     9065     81 0/subop/add %esp 8/imm32
     9066     # . epilogue
     9067     5d/pop-to-ebp
     9068     c3/return
     9069
     9070 test-copy-byte-to-with-invalid-output-type:
     9071     # . prologue
     9072     55/push-ebp
     9073     89/<- %ebp 4/r32/esp
     9074     # setup
     9075     (clear-stream _test-input-stream)
     9076     (clear-stream $_test-input-buffered-file->buffer)
     9077     (clear-stream _test-output-stream)
     9078     (clear-stream $_test-output-buffered-file->buffer)
     9079     (clear-stream _test-error-stream)
     9080     (clear-stream $_test-error-buffered-file->buffer)
     9081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9082     68/push 0/imm32
     9083     68/push 0/imm32
     9084     89/<- %edx 4/r32/esp
     9085     (tailor-exit-descriptor %edx 0x10)
     9086     #
     9087     (write _test-input-stream "fn foo {\n")
     9088     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9089     (write _test-input-stream "  var y: int\n")
     9090     (write _test-input-stream "  copy-byte-to y, x\n")
     9091     (write _test-input-stream "}\n")
     9092     # convert
     9093     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9094     # registers except esp clobbered at this point
     9095     # restore ed
     9096     89/<- %edx 4/r32/esp
     9097     (flush _test-output-buffered-file)
     9098     (flush _test-error-buffered-file)
     9099 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9105     # check output
     9106     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
     9107     (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")
     9108     # check that stop(1) was called
     9109     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
     9110     # don't restore from ebp
     9111     81 0/subop/add %esp 8/imm32
     9112     # . epilogue
     9113     5d/pop-to-ebp
     9114     c3/return
     9115
     9116 test-copy-byte-to-with-literal-inout:
     9117     # . prologue
     9118     55/push-ebp
     9119     89/<- %ebp 4/r32/esp
     9120     # setup
     9121     (clear-stream _test-input-stream)
     9122     (clear-stream $_test-input-buffered-file->buffer)
     9123     (clear-stream _test-output-stream)
     9124     (clear-stream $_test-output-buffered-file->buffer)
     9125     (clear-stream _test-error-stream)
     9126     (clear-stream $_test-error-buffered-file->buffer)
     9127     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9128     68/push 0/imm32
     9129     68/push 0/imm32
     9130     89/<- %edx 4/r32/esp
     9131     (tailor-exit-descriptor %edx 0x10)
     9132     #
     9133     (write _test-input-stream "fn foo {\n")
     9134     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9135     (write _test-input-stream "  copy-byte-to *x, 0\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-literal-inout: output should be empty")
     9152     (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")
     9153     # check that stop(1) was called
     9154     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: 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-deref-address:
     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     #
     9171     (write _test-input-stream "fn foo {\n")
     9172     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9173     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9174     (write _test-input-stream "  copy-byte-to *y, x\n")
     9175     (write _test-input-stream "}\n")
     9176     # convert
     9177     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9178     (flush _test-output-buffered-file)
     9179     # no errors
     9180     # . epilogue
     9181     5d/pop-to-ebp
     9182     c3/return
     9183
     9184 test-copy-byte-to-from-non-scalar-inout:
     9185     # . prologue
     9186     55/push-ebp
     9187     89/<- %ebp 4/r32/esp
     9188     # setup
     9189     (clear-stream _test-input-stream)
     9190     (clear-stream $_test-input-buffered-file->buffer)
     9191     (clear-stream _test-output-stream)
     9192     (clear-stream $_test-output-buffered-file->buffer)
     9193     (clear-stream _test-error-stream)
     9194     (clear-stream $_test-error-buffered-file->buffer)
     9195     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9196     68/push 0/imm32
     9197     68/push 0/imm32
     9198     89/<- %edx 4/r32/esp
     9199     (tailor-exit-descriptor %edx 0x10)
     9200     #
     9201     (write _test-input-stream "fn foo {\n")
     9202     (write _test-input-stream "  var x: (handle int)\n")
     9203     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     9204     (write _test-input-stream "  copy-byte-to *y, x\n")
     9205     (write _test-input-stream "}\n")
     9206     # convert
     9207     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9208     # registers except esp clobbered at this point
     9209     # restore ed
     9210     89/<- %edx 4/r32/esp
     9211     (flush _test-output-buffered-file)
     9212     (flush _test-error-buffered-file)
     9213 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9219     # check output
     9220     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
     9221     (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")
     9222     # check that stop(1) was called
     9223     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
     9224     # don't restore from ebp
     9225     81 0/subop/add %esp 8/imm32
     9226     # . epilogue
     9227     5d/pop-to-ebp
     9228     c3/return
     9229
     9230 test-compare-with-no-inout:
     9231     # . prologue
     9232     55/push-ebp
     9233     89/<- %ebp 4/r32/esp
     9234     # setup
     9235     (clear-stream _test-input-stream)
     9236     (clear-stream $_test-input-buffered-file->buffer)
     9237     (clear-stream _test-output-stream)
     9238     (clear-stream $_test-output-buffered-file->buffer)
     9239     (clear-stream _test-error-stream)
     9240     (clear-stream $_test-error-buffered-file->buffer)
     9241     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9242     68/push 0/imm32
     9243     68/push 0/imm32
     9244     89/<- %edx 4/r32/esp
     9245     (tailor-exit-descriptor %edx 0x10)
     9246     #
     9247     (write _test-input-stream "fn foo {\n")
     9248     (write _test-input-stream "  var x: boolean\n")
     9249     (write _test-input-stream "  compare\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-compare-with-no-inout: output should be empty")
     9266     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
     9267     # check that stop(1) was called
     9268     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-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-just-one-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 x\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-just-one-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-just-one-inout: error message")
     9312     # check that stop(1) was called
     9313     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-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-too-many-inouts:
     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, 0, 0\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-too-many-inouts: 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-too-many-inouts: error message")
     9357     # check that stop(1) was called
     9358     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: 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-output:
     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/eax: boolean <- copy 0\n")
     9384     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9385     (write _test-input-stream "  x <- compare y, 0\n")
     9386     (write _test-input-stream "}\n")
     9387     # convert
     9388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9389     # registers except esp clobbered at this point
     9390     # restore ed
     9391     89/<- %edx 4/r32/esp
     9392     (flush _test-output-buffered-file)
     9393     (flush _test-error-buffered-file)
     9394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9400     # check output
     9401     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
     9402     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
     9403     # check that stop(1) was called
     9404     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
     9405     # don't restore from ebp
     9406     81 0/subop/add %esp 8/imm32
     9407     # . epilogue
     9408     5d/pop-to-ebp
     9409     c3/return
     9410
     9411 test-compare-invalid-value-to-address:
     9412     # . prologue
     9413     55/push-ebp
     9414     89/<- %ebp 4/r32/esp
     9415     # setup
     9416     (clear-stream _test-input-stream)
     9417     (clear-stream $_test-input-buffered-file->buffer)
     9418     (clear-stream _test-output-stream)
     9419     (clear-stream $_test-output-buffered-file->buffer)
     9420     (clear-stream _test-error-stream)
     9421     (clear-stream $_test-error-buffered-file->buffer)
     9422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9423     68/push 0/imm32
     9424     68/push 0/imm32
     9425     89/<- %edx 4/r32/esp
     9426     (tailor-exit-descriptor %edx 0x10)
     9427     #
     9428     (write _test-input-stream "fn foo {\n")
     9429     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     9430     (write _test-input-stream "  var y: (addr int)\n")
     9431     (write _test-input-stream "  compare y, x\n")
     9432     (write _test-input-stream "}\n")
     9433     # convert
     9434     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9435     # registers except esp clobbered at this point
     9436     # restore ed
     9437     89/<- %edx 4/r32/esp
     9438     (flush _test-output-buffered-file)
     9439     (flush _test-error-buffered-file)
     9440 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9446     # check output
     9447     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
     9448     (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")
     9449     # check that stop(1) was called
     9450     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
     9451     # don't restore from ebp
     9452     81 0/subop/add %esp 8/imm32
     9453     # . epilogue
     9454     5d/pop-to-ebp
     9455     c3/return
     9456
     9457 test-compare-address:
     9458     # . prologue
     9459     55/push-ebp
     9460     89/<- %ebp 4/r32/esp
     9461     # setup
     9462     (clear-stream _test-input-stream)
     9463     (clear-stream $_test-input-buffered-file->buffer)
     9464     (clear-stream _test-output-stream)
     9465     (clear-stream $_test-output-buffered-file->buffer)
     9466     #
     9467     (write _test-input-stream "fn foo {\n")
     9468     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9469     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     9470     (write _test-input-stream "  compare y, x\n")
     9471     (write _test-input-stream "}\n")
     9472     # convert
     9473     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9474     (flush _test-output-buffered-file)
     9475     # no errors
     9476     # . epilogue
     9477     5d/pop-to-ebp
     9478     c3/return
     9479
     9480 test-compare-deref-address:
     9481     # . prologue
     9482     55/push-ebp
     9483     89/<- %ebp 4/r32/esp
     9484     # setup
     9485     (clear-stream _test-input-stream)
     9486     (clear-stream $_test-input-buffered-file->buffer)
     9487     (clear-stream _test-output-stream)
     9488     (clear-stream $_test-output-buffered-file->buffer)
     9489     #
     9490     (write _test-input-stream "fn foo {\n")
     9491     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9492     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     9493     (write _test-input-stream "  compare *y, x\n")
     9494     (write _test-input-stream "}\n")
     9495     # convert
     9496     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9497     (flush _test-output-buffered-file)
     9498     # no errors
     9499     # . epilogue
     9500     5d/pop-to-ebp
     9501     c3/return
     9502
     9503 test-compare-two-vars-in-memory:
     9504     # . prologue
     9505     55/push-ebp
     9506     89/<- %ebp 4/r32/esp
     9507     # setup
     9508     (clear-stream _test-input-stream)
     9509     (clear-stream $_test-input-buffered-file->buffer)
     9510     (clear-stream _test-output-stream)
     9511     (clear-stream $_test-output-buffered-file->buffer)
     9512     (clear-stream _test-error-stream)
     9513     (clear-stream $_test-error-buffered-file->buffer)
     9514     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9515     68/push 0/imm32
     9516     68/push 0/imm32
     9517     89/<- %edx 4/r32/esp
     9518     (tailor-exit-descriptor %edx 0x10)
     9519     #
     9520     (write _test-input-stream "fn foo {\n")
     9521     (write _test-input-stream "  var x: boolean\n")
     9522     (write _test-input-stream "  compare x, x\n")
     9523     (write _test-input-stream "}\n")
     9524     # convert
     9525     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9526     # registers except esp clobbered at this point
     9527     # restore ed
     9528     89/<- %edx 4/r32/esp
     9529     (flush _test-output-buffered-file)
     9530     (flush _test-error-buffered-file)
     9531 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9537     # check output
     9538     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
     9539     (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")
     9540     # check that stop(1) was called
     9541     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
     9542     # don't restore from ebp
     9543     81 0/subop/add %esp 8/imm32
     9544     # . epilogue
     9545     5d/pop-to-ebp
     9546     c3/return
     9547
     9548 test-compare-non-scalar:
     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: (handle int)\n")
     9567     (write _test-input-stream "  var y: int\n")
     9568     (write _test-input-stream "  compare y, x\n")
     9569     (write _test-input-stream "}\n")
     9570     # convert
     9571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9572     # registers except esp clobbered at this point
     9573     # restore ed
     9574     89/<- %edx 4/r32/esp
     9575     (flush _test-output-buffered-file)
     9576     (flush _test-error-buffered-file)
     9577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9583     # check output
     9584     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
     9585 #?     (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")
     9586     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
     9587     # check that stop(1) was called
     9588     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
     9589     # don't restore from ebp
     9590     81 0/subop/add %esp 8/imm32
     9591     # . epilogue
     9592     5d/pop-to-ebp
     9593     c3/return
     9594
     9595 test-compare-with-string-literal:
     9596     # . prologue
     9597     55/push-ebp
     9598     89/<- %ebp 4/r32/esp
     9599     # setup
     9600     (clear-stream _test-input-stream)
     9601     (clear-stream $_test-input-buffered-file->buffer)
     9602     (clear-stream _test-output-stream)
     9603     (clear-stream $_test-output-buffered-file->buffer)
     9604     (clear-stream _test-error-stream)
     9605     (clear-stream $_test-error-buffered-file->buffer)
     9606     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9607     68/push 0/imm32
     9608     68/push 0/imm32
     9609     89/<- %edx 4/r32/esp
     9610     (tailor-exit-descriptor %edx 0x10)
     9611     #
     9612     (write _test-input-stream "fn foo {\n")
     9613     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
     9614     (write _test-input-stream "  compare x, \"abc\"\n")
     9615     (write _test-input-stream "}\n")
     9616     # convert
     9617     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9618     # registers except esp clobbered at this point
     9619     # restore ed
     9620     89/<- %edx 4/r32/esp
     9621     (flush _test-output-buffered-file)
     9622     (flush _test-error-buffered-file)
     9623 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9629     # check output
     9630     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
     9631     (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")
     9632     # check that stop(1) was called
     9633     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: 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-address-with-no-inout:
     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: boolean <- address\n")
     9659     (write _test-input-stream "}\n")
     9660     # convert
     9661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9662     # registers except esp clobbered at this point
     9663     # restore ed
     9664     89/<- %edx 4/r32/esp
     9665     (flush _test-output-buffered-file)
     9666     (flush _test-error-buffered-file)
     9667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9673     # check output
     9674     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
     9675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
     9676     # check that stop(1) was called
     9677     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
     9678     # don't restore from ebp
     9679     81 0/subop/add %esp 8/imm32
     9680     # . epilogue
     9681     5d/pop-to-ebp
     9682     c3/return
     9683
     9684 test-address-with-multiple-inouts:
     9685     # . prologue
     9686     55/push-ebp
     9687     89/<- %ebp 4/r32/esp
     9688     # setup
     9689     (clear-stream _test-input-stream)
     9690     (clear-stream $_test-input-buffered-file->buffer)
     9691     (clear-stream _test-output-stream)
     9692     (clear-stream $_test-output-buffered-file->buffer)
     9693     (clear-stream _test-error-stream)
     9694     (clear-stream $_test-error-buffered-file->buffer)
     9695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9696     68/push 0/imm32
     9697     68/push 0/imm32
     9698     89/<- %edx 4/r32/esp
     9699     (tailor-exit-descriptor %edx 0x10)
     9700     #
     9701     (write _test-input-stream "fn foo {\n")
     9702     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
     9703     (write _test-input-stream "}\n")
     9704     # convert
     9705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9706     # registers except esp clobbered at this point
     9707     # restore ed
     9708     89/<- %edx 4/r32/esp
     9709     (flush _test-output-buffered-file)
     9710     (flush _test-error-buffered-file)
     9711 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9717     # check output
     9718     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
     9719     (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")
     9720     # check that stop(1) was called
     9721     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
     9722     # don't restore from ebp
     9723     81 0/subop/add %esp 8/imm32
     9724     # . epilogue
     9725     5d/pop-to-ebp
     9726     c3/return
     9727
     9728 test-address-with-no-output:
     9729     # . prologue
     9730     55/push-ebp
     9731     89/<- %ebp 4/r32/esp
     9732     # setup
     9733     (clear-stream _test-input-stream)
     9734     (clear-stream $_test-input-buffered-file->buffer)
     9735     (clear-stream _test-output-stream)
     9736     (clear-stream $_test-output-buffered-file->buffer)
     9737     (clear-stream _test-error-stream)
     9738     (clear-stream $_test-error-buffered-file->buffer)
     9739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9740     68/push 0/imm32
     9741     68/push 0/imm32
     9742     89/<- %edx 4/r32/esp
     9743     (tailor-exit-descriptor %edx 0x10)
     9744     #
     9745     (write _test-input-stream "fn foo {\n")
     9746     (write _test-input-stream "  address 0\n")
     9747     (write _test-input-stream "}\n")
     9748     # convert
     9749     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9750     # registers except esp clobbered at this point
     9751     # restore ed
     9752     89/<- %edx 4/r32/esp
     9753     (flush _test-output-buffered-file)
     9754     (flush _test-error-buffered-file)
     9755 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9761     # check output
     9762     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
     9763     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
     9764     # check that stop(1) was called
     9765     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
     9766     # don't restore from ebp
     9767     81 0/subop/add %esp 8/imm32
     9768     # . epilogue
     9769     5d/pop-to-ebp
     9770     c3/return
     9771
     9772 test-address-with-multiple-outputs:
     9773     # . prologue
     9774     55/push-ebp
     9775     89/<- %ebp 4/r32/esp
     9776     # setup
     9777     (clear-stream _test-input-stream)
     9778     (clear-stream $_test-input-buffered-file->buffer)
     9779     (clear-stream _test-output-stream)
     9780     (clear-stream $_test-output-buffered-file->buffer)
     9781     (clear-stream _test-error-stream)
     9782     (clear-stream $_test-error-buffered-file->buffer)
     9783     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9784     68/push 0/imm32
     9785     68/push 0/imm32
     9786     89/<- %edx 4/r32/esp
     9787     (tailor-exit-descriptor %edx 0x10)
     9788     #
     9789     (write _test-input-stream "fn foo {\n")
     9790     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9791     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9792     (write _test-input-stream "  x, y <- address 0\n")
     9793     (write _test-input-stream "}\n")
     9794     # convert
     9795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9796     # registers except esp clobbered at this point
     9797     # restore ed
     9798     89/<- %edx 4/r32/esp
     9799     (flush _test-output-buffered-file)
     9800     (flush _test-error-buffered-file)
     9801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9807     # check output
     9808     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
     9809     (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")
     9810     # check that stop(1) was called
     9811     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
     9812     # don't restore from ebp
     9813     81 0/subop/add %esp 8/imm32
     9814     # . epilogue
     9815     5d/pop-to-ebp
     9816     c3/return
     9817
     9818 # silly but it works
     9819 test-address-of-deref:
     9820     # . prologue
     9821     55/push-ebp
     9822     89/<- %ebp 4/r32/esp
     9823     # setup
     9824     (clear-stream _test-input-stream)
     9825     (clear-stream $_test-input-buffered-file->buffer)
     9826     (clear-stream _test-output-stream)
     9827     (clear-stream $_test-output-buffered-file->buffer)
     9828     #
     9829     (write _test-input-stream "fn foo {\n")
     9830     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9831     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
     9832     (write _test-input-stream "}\n")
     9833     # convert
     9834     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9835     (flush _test-output-buffered-file)
     9836     # no errors
     9837     # . epilogue
     9838     5d/pop-to-ebp
     9839     c3/return
     9840
     9841 test-address-to-non-register:
     9842     # . prologue
     9843     55/push-ebp
     9844     89/<- %ebp 4/r32/esp
     9845     # setup
     9846     (clear-stream _test-input-stream)
     9847     (clear-stream $_test-input-buffered-file->buffer)
     9848     (clear-stream _test-output-stream)
     9849     (clear-stream $_test-output-buffered-file->buffer)
     9850     (clear-stream _test-error-stream)
     9851     (clear-stream $_test-error-buffered-file->buffer)
     9852     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9853     68/push 0/imm32
     9854     68/push 0/imm32
     9855     89/<- %edx 4/r32/esp
     9856     (tailor-exit-descriptor %edx 0x10)
     9857     #
     9858     (write _test-input-stream "fn foo {\n")
     9859     (write _test-input-stream "  var x: (addr int)\n")
     9860     (write _test-input-stream "  x <- address 0\n")
     9861     (write _test-input-stream "}\n")
     9862     # convert
     9863     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9864     # registers except esp clobbered at this point
     9865     # restore ed
     9866     89/<- %edx 4/r32/esp
     9867     (flush _test-output-buffered-file)
     9868     (flush _test-error-buffered-file)
     9869 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9875     # check output
     9876     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
     9877     (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")
     9878     # check that stop(1) was called
     9879     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
     9880     # don't restore from ebp
     9881     81 0/subop/add %esp 8/imm32
     9882     # . epilogue
     9883     5d/pop-to-ebp
     9884     c3/return
     9885
     9886 test-address-with-wrong-type:
     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: int\n")
     9905     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\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-with-wrong-type: output should be empty")
     9922     (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")
     9923     # check that stop(1) was called
     9924     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: 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-right-type-for-array:
     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     #
     9941     (write _test-input-stream "fn foo {\n")
     9942     (write _test-input-stream "  var x: (array int 3)\n")
     9943     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
     9944     (write _test-input-stream "}\n")
     9945     # convert
     9946     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9947     (flush _test-output-buffered-file)
     9948     # no errors
     9949     # . epilogue
     9950     89/<- %esp 5/r32/ebp
     9951     5d/pop-to-ebp
     9952     c3/return
     9953
     9954 test-address-with-right-type-for-stream:
     9955     # . prologue
     9956     55/push-ebp
     9957     89/<- %ebp 4/r32/esp
     9958     # setup
     9959     (clear-stream _test-input-stream)
     9960     (clear-stream $_test-input-buffered-file->buffer)
     9961     (clear-stream _test-output-stream)
     9962     (clear-stream $_test-output-buffered-file->buffer)
     9963     #
     9964     (write _test-input-stream "fn foo {\n")
     9965     (write _test-input-stream "  var x: (stream int 3)\n")
     9966     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
     9967     (write _test-input-stream "}\n")
     9968     # convert
     9969     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9970     (flush _test-output-buffered-file)
     9971     # no errors
     9972     # . epilogue
     9973     89/<- %esp 5/r32/ebp
     9974     5d/pop-to-ebp
     9975     c3/return
     9976
     9977 test-get-with-wrong-field:
     9978     # . prologue
     9979     55/push-ebp
     9980     89/<- %ebp 4/r32/esp
     9981     # setup
     9982     (clear-stream _test-input-stream)
     9983     (clear-stream $_test-input-buffered-file->buffer)
     9984     (clear-stream _test-output-stream)
     9985     (clear-stream $_test-output-buffered-file->buffer)
     9986     (clear-stream _test-error-stream)
     9987     (clear-stream $_test-error-buffered-file->buffer)
     9988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9989     68/push 0/imm32
     9990     68/push 0/imm32
     9991     89/<- %edx 4/r32/esp
     9992     (tailor-exit-descriptor %edx 0x10)
     9993     #
     9994     (write _test-input-stream "fn foo {\n")
     9995     (write _test-input-stream "  var a: t\n")
     9996     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     9997     (write _test-input-stream "}\n")
     9998     (write _test-input-stream "type t {\n")
     9999     (write _test-input-stream "  x: int\n")
    10000     (write _test-input-stream "}\n")
    10001     # convert
    10002     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10003     # registers except esp clobbered at this point
    10004     # restore ed
    10005     89/<- %edx 4/r32/esp
    10006     (flush _test-output-buffered-file)
    10007     (flush _test-error-buffered-file)
    10008 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10014     # check output
    10015     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
    10016     (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")
    10017     # check that stop(1) was called
    10018     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
    10019     # don't restore from ebp
    10020     81 0/subop/add %esp 8/imm32
    10021     # . epilogue
    10022     5d/pop-to-ebp
    10023     c3/return
    10024
    10025 test-get-with-wrong-base-type:
    10026     # . prologue
    10027     55/push-ebp
    10028     89/<- %ebp 4/r32/esp
    10029     # setup
    10030     (clear-stream _test-input-stream)
    10031     (clear-stream $_test-input-buffered-file->buffer)
    10032     (clear-stream _test-output-stream)
    10033     (clear-stream $_test-output-buffered-file->buffer)
    10034     (clear-stream _test-error-stream)
    10035     (clear-stream $_test-error-buffered-file->buffer)
    10036     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10037     68/push 0/imm32
    10038     68/push 0/imm32
    10039     89/<- %edx 4/r32/esp
    10040     (tailor-exit-descriptor %edx 0x10)
    10041     #
    10042     (write _test-input-stream "fn foo {\n")
    10043     (write _test-input-stream "  var a: int\n")
    10044     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\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-base-type: output should be empty")
    10061     (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")
    10062     # check that stop(1) was called
    10063     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: 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-2:
    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: (addr t)\n")
    10089     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10090     (write _test-input-stream "}\n")
    10091     (write _test-input-stream "type t {\n")
    10092     (write _test-input-stream "  x: int\n")
    10093     (write _test-input-stream "}\n")
    10094     # convert
    10095     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10096     # registers except esp clobbered at this point
    10097     # restore ed
    10098     89/<- %edx 4/r32/esp
    10099     (flush _test-output-buffered-file)
    10100     (flush _test-error-buffered-file)
    10101 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10107     # check output
    10108     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
    10109     (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")
    10110     # check that stop(1) was called
    10111     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
    10112     # don't restore from ebp
    10113     81 0/subop/add %esp 8/imm32
    10114     # . epilogue
    10115     5d/pop-to-ebp
    10116     c3/return
    10117
    10118 test-get-with-wrong-base-type-3:
    10119     # . prologue
    10120     55/push-ebp
    10121     89/<- %ebp 4/r32/esp
    10122     # setup
    10123     (clear-stream _test-input-stream)
    10124     (clear-stream $_test-input-buffered-file->buffer)
    10125     (clear-stream _test-output-stream)
    10126     (clear-stream $_test-output-buffered-file->buffer)
    10127     (clear-stream _test-error-stream)
    10128     (clear-stream $_test-error-buffered-file->buffer)
    10129     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10130     68/push 0/imm32
    10131     68/push 0/imm32
    10132     89/<- %edx 4/r32/esp
    10133     (tailor-exit-descriptor %edx 0x10)
    10134     #
    10135     (write _test-input-stream "fn foo {\n")
    10136     (write _test-input-stream "  var a: (handle int)\n")
    10137     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\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-3: output should be empty")
    10154     (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")
    10155     # check that stop(1) was called
    10156     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: 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-offset-type:
    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: t\n")
    10182     (write _test-input-stream "  var b: int\n")
    10183     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
    10184     (write _test-input-stream "}\n")
    10185     (write _test-input-stream "type t {\n")
    10186     (write _test-input-stream "  x: int\n")
    10187     (write _test-input-stream "}\n")
    10188     # convert
    10189     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10190     # registers except esp clobbered at this point
    10191     # restore ed
    10192     89/<- %edx 4/r32/esp
    10193     (flush _test-output-buffered-file)
    10194     (flush _test-error-buffered-file)
    10195 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10201     # check output
    10202     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
    10203     (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")
    10204     # check that stop(1) was called
    10205     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
    10206     # don't restore from ebp
    10207     81 0/subop/add %esp 8/imm32
    10208     # . epilogue
    10209     5d/pop-to-ebp
    10210     c3/return
    10211
    10212 test-get-with-wrong-output-type:
    10213     # . prologue
    10214     55/push-ebp
    10215     89/<- %ebp 4/r32/esp
    10216     # setup
    10217     (clear-stream _test-input-stream)
    10218     (clear-stream $_test-input-buffered-file->buffer)
    10219     (clear-stream _test-output-stream)
    10220     (clear-stream $_test-output-buffered-file->buffer)
    10221     (clear-stream _test-error-stream)
    10222     (clear-stream $_test-error-buffered-file->buffer)
    10223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10224     68/push 0/imm32
    10225     68/push 0/imm32
    10226     89/<- %edx 4/r32/esp
    10227     (tailor-exit-descriptor %edx 0x10)
    10228     #
    10229     (write _test-input-stream "fn foo {\n")
    10230     (write _test-input-stream "  var a: t\n")
    10231     (write _test-input-stream "  var c: (addr int)\n")
    10232     (write _test-input-stream "  c <- get a, x\n")
    10233     (write _test-input-stream "}\n")
    10234     (write _test-input-stream "type t {\n")
    10235     (write _test-input-stream "  x: int\n")
    10236     (write _test-input-stream "}\n")
    10237     # convert
    10238     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10239     # registers except esp clobbered at this point
    10240     # restore ed
    10241     89/<- %edx 4/r32/esp
    10242     (flush _test-output-buffered-file)
    10243     (flush _test-error-buffered-file)
    10244 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10250     # check output
    10251     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
    10252     (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")
    10253     # check that stop(1) was called
    10254     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
    10255     # don't restore from ebp
    10256     81 0/subop/add %esp 8/imm32
    10257     # . epilogue
    10258     5d/pop-to-ebp
    10259     c3/return
    10260
    10261 test-get-with-wrong-output-type-2:
    10262     # . prologue
    10263     55/push-ebp
    10264     89/<- %ebp 4/r32/esp
    10265     # setup
    10266     (clear-stream _test-input-stream)
    10267     (clear-stream $_test-input-buffered-file->buffer)
    10268     (clear-stream _test-output-stream)
    10269     (clear-stream $_test-output-buffered-file->buffer)
    10270     (clear-stream _test-error-stream)
    10271     (clear-stream $_test-error-buffered-file->buffer)
    10272     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10273     68/push 0/imm32
    10274     68/push 0/imm32
    10275     89/<- %edx 4/r32/esp
    10276     (tailor-exit-descriptor %edx 0x10)
    10277     #
    10278     (write _test-input-stream "fn foo {\n")
    10279     (write _test-input-stream "  var a: t\n")
    10280     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
    10281     (write _test-input-stream "}\n")
    10282     (write _test-input-stream "type t {\n")
    10283     (write _test-input-stream "  x: int\n")
    10284     (write _test-input-stream "}\n")
    10285     # convert
    10286     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10287     # registers except esp clobbered at this point
    10288     # restore ed
    10289     89/<- %edx 4/r32/esp
    10290     (flush _test-output-buffered-file)
    10291     (flush _test-error-buffered-file)
    10292 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10298     # check output
    10299     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
    10300     (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")
    10301     # check that stop(1) was called
    10302     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
    10303     # don't restore from ebp
    10304     81 0/subop/add %esp 8/imm32
    10305     # . epilogue
    10306     5d/pop-to-ebp
    10307     c3/return
    10308
    10309 test-get-with-wrong-output-type-3:
    10310     # . prologue
    10311     55/push-ebp
    10312     89/<- %ebp 4/r32/esp
    10313     # setup
    10314     (clear-stream _test-input-stream)
    10315     (clear-stream $_test-input-buffered-file->buffer)
    10316     (clear-stream _test-output-stream)
    10317     (clear-stream $_test-output-buffered-file->buffer)
    10318     (clear-stream _test-error-stream)
    10319     (clear-stream $_test-error-buffered-file->buffer)
    10320     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10321     68/push 0/imm32
    10322     68/push 0/imm32
    10323     89/<- %edx 4/r32/esp
    10324     (tailor-exit-descriptor %edx 0x10)
    10325     #
    10326     (write _test-input-stream "fn foo {\n")
    10327     (write _test-input-stream "  var a: t\n")
    10328     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
    10329     (write _test-input-stream "}\n")
    10330     (write _test-input-stream "type t {\n")
    10331     (write _test-input-stream "  x: int\n")
    10332     (write _test-input-stream "}\n")
    10333     # convert
    10334     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10335     # registers except esp clobbered at this point
    10336     # restore ed
    10337     89/<- %edx 4/r32/esp
    10338     (flush _test-output-buffered-file)
    10339     (flush _test-error-buffered-file)
    10340 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10346     # check output
    10347     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
    10348     (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")
    10349     # check that stop(1) was called
    10350     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
    10351     # don't restore from ebp
    10352     81 0/subop/add %esp 8/imm32
    10353     # . epilogue
    10354     5d/pop-to-ebp
    10355     c3/return
    10356
    10357 test-get-with-wrong-output-type-4:
    10358     # . prologue
    10359     55/push-ebp
    10360     89/<- %ebp 4/r32/esp
    10361     # setup
    10362     (clear-stream _test-input-stream)
    10363     (clear-stream $_test-input-buffered-file->buffer)
    10364     (clear-stream _test-output-stream)
    10365     (clear-stream $_test-output-buffered-file->buffer)
    10366     (clear-stream _test-error-stream)
    10367     (clear-stream $_test-error-buffered-file->buffer)
    10368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10369     68/push 0/imm32
    10370     68/push 0/imm32
    10371     89/<- %edx 4/r32/esp
    10372     (tailor-exit-descriptor %edx 0x10)
    10373     #
    10374     (write _test-input-stream "fn foo {\n")
    10375     (write _test-input-stream "  var a: t\n")
    10376     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
    10377     (write _test-input-stream "}\n")
    10378     (write _test-input-stream "type t {\n")
    10379     (write _test-input-stream "  x: int\n")
    10380     (write _test-input-stream "}\n")
    10381     # convert
    10382     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10383     # registers except esp clobbered at this point
    10384     # restore ed
    10385     89/<- %edx 4/r32/esp
    10386     (flush _test-output-buffered-file)
    10387     (flush _test-error-buffered-file)
    10388 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10394     # check output
    10395     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
    10396     (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")
    10397     # check that stop(1) was called
    10398     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
    10399     # don't restore from ebp
    10400     81 0/subop/add %esp 8/imm32
    10401     # . epilogue
    10402     5d/pop-to-ebp
    10403     c3/return
    10404
    10405 test-get-with-wrong-output-type-5:
    10406     # . prologue
    10407     55/push-ebp
    10408     89/<- %ebp 4/r32/esp
    10409     # setup
    10410     (clear-stream _test-input-stream)
    10411     (clear-stream $_test-input-buffered-file->buffer)
    10412     (clear-stream _test-output-stream)
    10413     (clear-stream $_test-output-buffered-file->buffer)
    10414     #
    10415     (write _test-input-stream "fn foo {\n")
    10416     (write _test-input-stream "  var a: t\n")
    10417     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
    10418     (write _test-input-stream "}\n")
    10419     (write _test-input-stream "type t {\n")
    10420     (write _test-input-stream "  x: (handle int)\n")
    10421     (write _test-input-stream "}\n")
    10422     # convert
    10423     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10424     (flush _test-output-buffered-file)
    10425     # no errors
    10426     # . epilogue
    10427     89/<- %esp 5/r32/ebp
    10428     5d/pop-to-ebp
    10429     c3/return
    10430
    10431 test-get-with-too-few-inouts:
    10432     # . prologue
    10433     55/push-ebp
    10434     89/<- %ebp 4/r32/esp
    10435     # setup
    10436     (clear-stream _test-input-stream)
    10437     (clear-stream $_test-input-buffered-file->buffer)
    10438     (clear-stream _test-output-stream)
    10439     (clear-stream $_test-output-buffered-file->buffer)
    10440     (clear-stream _test-error-stream)
    10441     (clear-stream $_test-error-buffered-file->buffer)
    10442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10443     68/push 0/imm32
    10444     68/push 0/imm32
    10445     89/<- %edx 4/r32/esp
    10446     (tailor-exit-descriptor %edx 0x10)
    10447     #
    10448     (write _test-input-stream "fn foo {\n")
    10449     (write _test-input-stream "  var a: t\n")
    10450     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
    10451     (write _test-input-stream "}\n")
    10452     (write _test-input-stream "type t {\n")
    10453     (write _test-input-stream "  x: int\n")
    10454     (write _test-input-stream "}\n")
    10455     # convert
    10456     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10457     # registers except esp clobbered at this point
    10458     # restore ed
    10459     89/<- %edx 4/r32/esp
    10460     (flush _test-output-buffered-file)
    10461     (flush _test-error-buffered-file)
    10462 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10468     # check output
    10469     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
    10470     (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")
    10471     # check that stop(1) was called
    10472     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
    10473     # don't restore from ebp
    10474     81 0/subop/add %esp 8/imm32
    10475     # . epilogue
    10476     5d/pop-to-ebp
    10477     c3/return
    10478
    10479 test-get-with-too-many-inouts:
    10480     # . prologue
    10481     55/push-ebp
    10482     89/<- %ebp 4/r32/esp
    10483     # setup
    10484     (clear-stream _test-input-stream)
    10485     (clear-stream $_test-input-buffered-file->buffer)
    10486     (clear-stream _test-output-stream)
    10487     (clear-stream $_test-output-buffered-file->buffer)
    10488     (clear-stream _test-error-stream)
    10489     (clear-stream $_test-error-buffered-file->buffer)
    10490     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10491     68/push 0/imm32
    10492     68/push 0/imm32
    10493     89/<- %edx 4/r32/esp
    10494     (tailor-exit-descriptor %edx 0x10)
    10495     #
    10496     (write _test-input-stream "fn foo {\n")
    10497     (write _test-input-stream "  var a: t\n")
    10498     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
    10499     (write _test-input-stream "}\n")
    10500     (write _test-input-stream "type t {\n")
    10501     (write _test-input-stream "  x: int\n")
    10502     (write _test-input-stream "}\n")
    10503     # convert
    10504     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10505     # registers except esp clobbered at this point
    10506     # restore ed
    10507     89/<- %edx 4/r32/esp
    10508     (flush _test-output-buffered-file)
    10509     (flush _test-error-buffered-file)
    10510 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10516     # check output
    10517     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
    10518     (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")
    10519     # check that stop(1) was called
    10520     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
    10521     # don't restore from ebp
    10522     81 0/subop/add %esp 8/imm32
    10523     # . epilogue
    10524     5d/pop-to-ebp
    10525     c3/return
    10526
    10527 test-get-with-no-output:
    10528     # . prologue
    10529     55/push-ebp
    10530     89/<- %ebp 4/r32/esp
    10531     # setup
    10532     (clear-stream _test-input-stream)
    10533     (clear-stream $_test-input-buffered-file->buffer)
    10534     (clear-stream _test-output-stream)
    10535     (clear-stream $_test-output-buffered-file->buffer)
    10536     (clear-stream _test-error-stream)
    10537     (clear-stream $_test-error-buffered-file->buffer)
    10538     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10539     68/push 0/imm32
    10540     68/push 0/imm32
    10541     89/<- %edx 4/r32/esp
    10542     (tailor-exit-descriptor %edx 0x10)
    10543     #
    10544     (write _test-input-stream "fn foo {\n")
    10545     (write _test-input-stream "  var a: t\n")
    10546     (write _test-input-stream "  get a, x\n")
    10547     (write _test-input-stream "}\n")
    10548     (write _test-input-stream "type t {\n")
    10549     (write _test-input-stream "  x: int\n")
    10550     (write _test-input-stream "}\n")
    10551     # convert
    10552     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10553     # registers except esp clobbered at this point
    10554     # restore ed
    10555     89/<- %edx 4/r32/esp
    10556     (flush _test-output-buffered-file)
    10557     (flush _test-error-buffered-file)
    10558 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10564     # check output
    10565     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
    10566     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
    10567     # check that stop(1) was called
    10568     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
    10569     # don't restore from ebp
    10570     81 0/subop/add %esp 8/imm32
    10571     # . epilogue
    10572     5d/pop-to-ebp
    10573     c3/return
    10574
    10575 test-get-with-too-many-outputs:
    10576     # . prologue
    10577     55/push-ebp
    10578     89/<- %ebp 4/r32/esp
    10579     # setup
    10580     (clear-stream _test-input-stream)
    10581     (clear-stream $_test-input-buffered-file->buffer)
    10582     (clear-stream _test-output-stream)
    10583     (clear-stream $_test-output-buffered-file->buffer)
    10584     (clear-stream _test-error-stream)
    10585     (clear-stream $_test-error-buffered-file->buffer)
    10586     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10587     68/push 0/imm32
    10588     68/push 0/imm32
    10589     89/<- %edx 4/r32/esp
    10590     (tailor-exit-descriptor %edx 0x10)
    10591     #
    10592     (write _test-input-stream "fn foo {\n")
    10593     (write _test-input-stream "  var a: t\n")
    10594     (write _test-input-stream "  var b: int\n")
    10595     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
    10596     (write _test-input-stream "  c, b <- get a, x\n")
    10597     (write _test-input-stream "}\n")
    10598     (write _test-input-stream "type t {\n")
    10599     (write _test-input-stream "  x: int\n")
    10600     (write _test-input-stream "}\n")
    10601     # convert
    10602     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10603     # registers except esp clobbered at this point
    10604     # restore ed
    10605     89/<- %edx 4/r32/esp
    10606     (flush _test-output-buffered-file)
    10607     (flush _test-error-buffered-file)
    10608 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10614     # check output
    10615     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
    10616     (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")
    10617     # check that stop(1) was called
    10618     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
    10619     # don't restore from ebp
    10620     81 0/subop/add %esp 8/imm32
    10621     # . epilogue
    10622     5d/pop-to-ebp
    10623     c3/return
    10624
    10625 test-convert-array-of-user-defined-types:
    10626     # . prologue
    10627     55/push-ebp
    10628     89/<- %ebp 4/r32/esp
    10629     # setup
    10630     (clear-stream _test-input-stream)
    10631     (clear-stream $_test-input-buffered-file->buffer)
    10632     (clear-stream _test-output-stream)
    10633     (clear-stream $_test-output-buffered-file->buffer)
    10634     #
    10635     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10636     (write _test-input-stream "  x: int\n")
    10637     (write _test-input-stream "  y: int\n")
    10638     (write _test-input-stream "}\n")
    10639     (write _test-input-stream "fn foo {\n")
    10640     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10641     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
    10642     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
    10643     (write _test-input-stream "}\n")
    10644     # convert
    10645     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10646     (flush _test-output-buffered-file)
    10647 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10653     # check output
    10654     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
    10655     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
    10656     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
    10657     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
    10658     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
    10659     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
    10660     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
    10661     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
    10662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
    10663     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
    10664     (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")
    10665     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/11")
    10666     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
    10667     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
    10668     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
    10669     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
    10670     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
    10671     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
    10672     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
    10673     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
    10674     # . epilogue
    10675     89/<- %esp 5/r32/ebp
    10676     5d/pop-to-ebp
    10677     c3/return
    10678
    10679 test-convert-length-of-array-of-user-defined-types-to-eax:
    10680     # . prologue
    10681     55/push-ebp
    10682     89/<- %ebp 4/r32/esp
    10683     # setup
    10684     (clear-stream _test-input-stream)
    10685     (clear-stream $_test-input-buffered-file->buffer)
    10686     (clear-stream _test-output-stream)
    10687     (clear-stream $_test-output-buffered-file->buffer)
    10688     #
    10689     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10690     (write _test-input-stream "  x: int\n")
    10691     (write _test-input-stream "  y: int\n")
    10692     (write _test-input-stream "  z: int\n")
    10693     (write _test-input-stream "}\n")
    10694     (write _test-input-stream "fn foo {\n")
    10695     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10696     (write _test-input-stream "  var x/eax: int <- length arr\n")
    10697     (write _test-input-stream "}\n")
    10698     # convert
    10699     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10700     (flush _test-output-buffered-file)
    10701 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10707     # check output
    10708     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
    10709     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
    10710     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
    10711     (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")
    10712     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
    10713     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
    10714     # var arr
    10715     (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")
    10716     (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")
    10717     # length instruction
    10718     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
    10719     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
    10720     (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")
    10721     (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")
    10722     (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")
    10723     (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")
    10724     (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")
    10725     (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")
    10726     # reclaim arr
    10727     (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")
    10728     #
    10729     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
    10730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
    10731     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
    10732     (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")
    10733     (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")
    10734     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
    10735     # . epilogue
    10736     89/<- %esp 5/r32/ebp
    10737     5d/pop-to-ebp
    10738     c3/return
    10739
    10740 test-convert-length-of-array-of-user-defined-types-to-ecx:
    10741     # . prologue
    10742     55/push-ebp
    10743     89/<- %ebp 4/r32/esp
    10744     # setup
    10745     (clear-stream _test-input-stream)
    10746     (clear-stream $_test-input-buffered-file->buffer)
    10747     (clear-stream _test-output-stream)
    10748     (clear-stream $_test-output-buffered-file->buffer)
    10749     #
    10750     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10751     (write _test-input-stream "  x: int\n")
    10752     (write _test-input-stream "  y: int\n")
    10753     (write _test-input-stream "  z: int\n")
    10754     (write _test-input-stream "}\n")
    10755     (write _test-input-stream "fn foo {\n")
    10756     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10757     (write _test-input-stream "  var x/ecx: int <- length arr\n")
    10758     (write _test-input-stream "}\n")
    10759     # convert
    10760     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10761     (flush _test-output-buffered-file)
    10762 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10768     # check output
    10769     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
    10770     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
    10771     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
    10772     (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")
    10773     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
    10774     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
    10775     # var a
    10776     (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")
    10777     (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")
    10778     # var x
    10779     (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")
    10780     # length instruction
    10781     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
    10782     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
    10783     (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")
    10784     (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")
    10785     (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")
    10786     (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")
    10787     (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")
    10788     (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")
    10789     (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")
    10790     # reclaim x
    10791     (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")
    10792     # reclaim a
    10793     (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")
    10794     #
    10795     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
    10796     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
    10797     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
    10798     (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")
    10799     (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")
    10800     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
    10801     # . epilogue
    10802     89/<- %esp 5/r32/ebp
    10803     5d/pop-to-ebp
    10804     c3/return
    10805
    10806 test-convert-length-of-array-of-user-defined-types-to-edx:
    10807     # . prologue
    10808     55/push-ebp
    10809     89/<- %ebp 4/r32/esp
    10810     # setup
    10811     (clear-stream _test-input-stream)
    10812     (clear-stream $_test-input-buffered-file->buffer)
    10813     (clear-stream _test-output-stream)
    10814     (clear-stream $_test-output-buffered-file->buffer)
    10815     #
    10816     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10817     (write _test-input-stream "  x: int\n")
    10818     (write _test-input-stream "  y: int\n")
    10819     (write _test-input-stream "  z: int\n")
    10820     (write _test-input-stream "}\n")
    10821     (write _test-input-stream "fn foo {\n")
    10822     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10823     (write _test-input-stream "  var x/edx: int <- length arr\n")
    10824     (write _test-input-stream "}\n")
    10825     # convert
    10826     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10827     (flush _test-output-buffered-file)
    10828 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10834     # check output
    10835     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
    10836     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
    10837     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
    10838     (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")
    10839     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
    10840     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
    10841     # var a
    10842     (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")
    10843     (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")
    10844     # var x
    10845     (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")
    10846     # length instruction
    10847     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
    10848     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
    10849     (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")
    10850     (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")
    10851     (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")
    10852     (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")
    10853     (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")
    10854     (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")
    10855     (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")
    10856     # reclaim x
    10857     (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")
    10858     # reclaim a
    10859     (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")
    10860     #
    10861     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
    10862     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
    10863     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
    10864     (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")
    10865     (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")
    10866     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
    10867     # . epilogue
    10868     89/<- %esp 5/r32/ebp
    10869     5d/pop-to-ebp
    10870     c3/return
    10871
    10872 test-convert-length-of-array-of-user-defined-types:
    10873     # . prologue
    10874     55/push-ebp
    10875     89/<- %ebp 4/r32/esp
    10876     # setup
    10877     (clear-stream _test-input-stream)
    10878     (clear-stream $_test-input-buffered-file->buffer)
    10879     (clear-stream _test-output-stream)
    10880     (clear-stream $_test-output-buffered-file->buffer)
    10881     #
    10882     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10883     (write _test-input-stream "  x: int\n")
    10884     (write _test-input-stream "  y: int\n")
    10885     (write _test-input-stream "  z: int\n")
    10886     (write _test-input-stream "}\n")
    10887     (write _test-input-stream "fn foo {\n")
    10888     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10889     (write _test-input-stream "  var x/ebx: int <- length arr\n")
    10890     (write _test-input-stream "}\n")
    10891     # convert
    10892     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10893     (flush _test-output-buffered-file)
    10894 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10900     # check output
    10901     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
    10902     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
    10903     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
    10904     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
    10905     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
    10906     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
    10907     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
    10908     (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")
    10909     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
    10910     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
    10911     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
    10912     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
    10913     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
    10914     (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")
    10915     (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")
    10916     (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")
    10917     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
    10918     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
    10919     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
    10920     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
    10921     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
    10922     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
    10923     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
    10924     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
    10925     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
    10926     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
    10927     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
    10928     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
    10929     # . epilogue
    10930     89/<- %esp 5/r32/ebp
    10931     5d/pop-to-ebp
    10932     c3/return
    10933
    10934 test-index-with-non-array-atom-base-type:
    10935     # . prologue
    10936     55/push-ebp
    10937     89/<- %ebp 4/r32/esp
    10938     # setup
    10939     (clear-stream _test-input-stream)
    10940     (clear-stream $_test-input-buffered-file->buffer)
    10941     (clear-stream _test-output-stream)
    10942     (clear-stream $_test-output-buffered-file->buffer)
    10943     (clear-stream _test-error-stream)
    10944     (clear-stream $_test-error-buffered-file->buffer)
    10945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10946     68/push 0/imm32
    10947     68/push 0/imm32
    10948     89/<- %edx 4/r32/esp
    10949     (tailor-exit-descriptor %edx 0x10)
    10950     #
    10951     (write _test-input-stream "fn foo {\n")
    10952     (write _test-input-stream "  var a: int\n")
    10953     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    10954     (write _test-input-stream "}\n")
    10955     # convert
    10956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10957     # registers except esp clobbered at this point
    10958     # restore ed
    10959     89/<- %edx 4/r32/esp
    10960     (flush _test-output-buffered-file)
    10961     (flush _test-error-buffered-file)
    10962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10968     # check output
    10969     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
    10970     (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")
    10971     # check that stop(1) was called
    10972     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
    10973     # don't restore from ebp
    10974     81 0/subop/add %esp 8/imm32
    10975     # . epilogue
    10976     5d/pop-to-ebp
    10977     c3/return
    10978
    10979 test-index-with-non-array-compound-base-type:
    10980     # . prologue
    10981     55/push-ebp
    10982     89/<- %ebp 4/r32/esp
    10983     # setup
    10984     (clear-stream _test-input-stream)
    10985     (clear-stream $_test-input-buffered-file->buffer)
    10986     (clear-stream _test-output-stream)
    10987     (clear-stream $_test-output-buffered-file->buffer)
    10988     (clear-stream _test-error-stream)
    10989     (clear-stream $_test-error-buffered-file->buffer)
    10990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10991     68/push 0/imm32
    10992     68/push 0/imm32
    10993     89/<- %edx 4/r32/esp
    10994     (tailor-exit-descriptor %edx 0x10)
    10995     #
    10996     (write _test-input-stream "fn foo {\n")
    10997     (write _test-input-stream "  var a: (handle int)\n")
    10998     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    10999     (write _test-input-stream "}\n")
    11000     # convert
    11001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11002     # registers except esp clobbered at this point
    11003     # restore ed
    11004     89/<- %edx 4/r32/esp
    11005     (flush _test-output-buffered-file)
    11006     (flush _test-error-buffered-file)
    11007 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11013     # check output
    11014     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
    11015     (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")
    11016     # check that stop(1) was called
    11017     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
    11018     # don't restore from ebp
    11019     81 0/subop/add %esp 8/imm32
    11020     # . epilogue
    11021     5d/pop-to-ebp
    11022     c3/return
    11023
    11024 test-index-with-non-array-compound-base-type-2:
    11025     # . prologue
    11026     55/push-ebp
    11027     89/<- %ebp 4/r32/esp
    11028     # setup
    11029     (clear-stream _test-input-stream)
    11030     (clear-stream $_test-input-buffered-file->buffer)
    11031     (clear-stream _test-output-stream)
    11032     (clear-stream $_test-output-buffered-file->buffer)
    11033     (clear-stream _test-error-stream)
    11034     (clear-stream $_test-error-buffered-file->buffer)
    11035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11036     68/push 0/imm32
    11037     68/push 0/imm32
    11038     89/<- %edx 4/r32/esp
    11039     (tailor-exit-descriptor %edx 0x10)
    11040     #
    11041     (write _test-input-stream "fn foo {\n")
    11042     (write _test-input-stream "  var a: (addr int)\n")
    11043     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11044     (write _test-input-stream "}\n")
    11045     # convert
    11046     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11047     # registers except esp clobbered at this point
    11048     # restore ed
    11049     89/<- %edx 4/r32/esp
    11050     (flush _test-output-buffered-file)
    11051     (flush _test-error-buffered-file)
    11052 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11058     # check output
    11059     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
    11060     (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")
    11061     # check that stop(1) was called
    11062     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
    11063     # don't restore from ebp
    11064     81 0/subop/add %esp 8/imm32
    11065     # . epilogue
    11066     5d/pop-to-ebp
    11067     c3/return
    11068
    11069 test-index-with-array-atom-base-type:
    11070     # . prologue
    11071     55/push-ebp
    11072     89/<- %ebp 4/r32/esp
    11073     # setup
    11074     (clear-stream _test-input-stream)
    11075     (clear-stream $_test-input-buffered-file->buffer)
    11076     (clear-stream _test-output-stream)
    11077     (clear-stream $_test-output-buffered-file->buffer)
    11078     (clear-stream _test-error-stream)
    11079     (clear-stream $_test-error-buffered-file->buffer)
    11080     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11081     68/push 0/imm32
    11082     68/push 0/imm32
    11083     89/<- %edx 4/r32/esp
    11084     (tailor-exit-descriptor %edx 0x10)
    11085     #
    11086     (write _test-input-stream "fn foo {\n")
    11087     (write _test-input-stream "  var a: array\n")
    11088     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11089     (write _test-input-stream "}\n")
    11090     # convert
    11091     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11092     # registers except esp clobbered at this point
    11093     # restore ed
    11094     89/<- %edx 4/r32/esp
    11095     (flush _test-output-buffered-file)
    11096     (flush _test-error-buffered-file)
    11097 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11103     # check output
    11104     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
    11105     (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")
    11106     # check that stop(1) was called
    11107     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
    11108     # don't restore from ebp
    11109     81 0/subop/add %esp 8/imm32
    11110     # . epilogue
    11111     5d/pop-to-ebp
    11112     c3/return
    11113
    11114 test-index-with-addr-base-on-stack:
    11115     # . prologue
    11116     55/push-ebp
    11117     89/<- %ebp 4/r32/esp
    11118     # setup
    11119     (clear-stream _test-input-stream)
    11120     (clear-stream $_test-input-buffered-file->buffer)
    11121     (clear-stream _test-output-stream)
    11122     (clear-stream $_test-output-buffered-file->buffer)
    11123     (clear-stream _test-error-stream)
    11124     (clear-stream $_test-error-buffered-file->buffer)
    11125     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11126     68/push 0/imm32
    11127     68/push 0/imm32
    11128     89/<- %edx 4/r32/esp
    11129     (tailor-exit-descriptor %edx 0x10)
    11130     #
    11131     (write _test-input-stream "fn foo {\n")
    11132     (write _test-input-stream "  var a: (addr array int)\n")
    11133     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11134     (write _test-input-stream "}\n")
    11135     # convert
    11136     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11137     # registers except esp clobbered at this point
    11138     # restore ed
    11139     89/<- %edx 4/r32/esp
    11140     (flush _test-output-buffered-file)
    11141     (flush _test-error-buffered-file)
    11142 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11148     # check output
    11149     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
    11150     (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")
    11151     # check that stop(1) was called
    11152     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
    11153     # don't restore from ebp
    11154     81 0/subop/add %esp 8/imm32
    11155     # . epilogue
    11156     5d/pop-to-ebp
    11157     c3/return
    11158
    11159 test-index-with-wrong-index-type:
    11160     # . prologue
    11161     55/push-ebp
    11162     89/<- %ebp 4/r32/esp
    11163     # setup
    11164     (clear-stream _test-input-stream)
    11165     (clear-stream $_test-input-buffered-file->buffer)
    11166     (clear-stream _test-output-stream)
    11167     (clear-stream $_test-output-buffered-file->buffer)
    11168     (clear-stream _test-error-stream)
    11169     (clear-stream $_test-error-buffered-file->buffer)
    11170     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11171     68/push 0/imm32
    11172     68/push 0/imm32
    11173     89/<- %edx 4/r32/esp
    11174     (tailor-exit-descriptor %edx 0x10)
    11175     #
    11176     (write _test-input-stream "fn foo {\n")
    11177     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11178     (write _test-input-stream "  var b: boolean\n")
    11179     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11180     (write _test-input-stream "}\n")
    11181     # convert
    11182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11183     # registers except esp clobbered at this point
    11184     # restore ed
    11185     89/<- %edx 4/r32/esp
    11186     (flush _test-output-buffered-file)
    11187     (flush _test-error-buffered-file)
    11188 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11194     # check output
    11195     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
    11196     (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")
    11197     # check that stop(1) was called
    11198     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
    11199     # don't restore from ebp
    11200     81 0/subop/add %esp 8/imm32
    11201     # . epilogue
    11202     5d/pop-to-ebp
    11203     c3/return
    11204
    11205 test-index-with-offset-atom-index-type:
    11206     # . prologue
    11207     55/push-ebp
    11208     89/<- %ebp 4/r32/esp
    11209     # setup
    11210     (clear-stream _test-input-stream)
    11211     (clear-stream $_test-input-buffered-file->buffer)
    11212     (clear-stream _test-output-stream)
    11213     (clear-stream $_test-output-buffered-file->buffer)
    11214     (clear-stream _test-error-stream)
    11215     (clear-stream $_test-error-buffered-file->buffer)
    11216     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11217     68/push 0/imm32
    11218     68/push 0/imm32
    11219     89/<- %edx 4/r32/esp
    11220     (tailor-exit-descriptor %edx 0x10)
    11221     #
    11222     (write _test-input-stream "fn foo {\n")
    11223     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11224     (write _test-input-stream "  var b: offset\n")
    11225     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11226     (write _test-input-stream "}\n")
    11227     # convert
    11228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11229     # registers except esp clobbered at this point
    11230     # restore ed
    11231     89/<- %edx 4/r32/esp
    11232     (flush _test-output-buffered-file)
    11233     (flush _test-error-buffered-file)
    11234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11240     # check output
    11241     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
    11242     (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")
    11243     # check that stop(1) was called
    11244     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
    11245     # don't restore from ebp
    11246     81 0/subop/add %esp 8/imm32
    11247     # . epilogue
    11248     5d/pop-to-ebp
    11249     c3/return
    11250
    11251 test-index-with-offset-on-stack:
    11252     # . prologue
    11253     55/push-ebp
    11254     89/<- %ebp 4/r32/esp
    11255     # setup
    11256     (clear-stream _test-input-stream)
    11257     (clear-stream $_test-input-buffered-file->buffer)
    11258     (clear-stream _test-output-stream)
    11259     (clear-stream $_test-output-buffered-file->buffer)
    11260     (clear-stream _test-error-stream)
    11261     (clear-stream $_test-error-buffered-file->buffer)
    11262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11263     68/push 0/imm32
    11264     68/push 0/imm32
    11265     89/<- %edx 4/r32/esp
    11266     (tailor-exit-descriptor %edx 0x10)
    11267     #
    11268     (write _test-input-stream "fn foo {\n")
    11269     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11270     (write _test-input-stream "  var b: int\n")
    11271     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11272     (write _test-input-stream "}\n")
    11273     # convert
    11274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11275     # registers except esp clobbered at this point
    11276     # restore ed
    11277     89/<- %edx 4/r32/esp
    11278     (flush _test-output-buffered-file)
    11279     (flush _test-error-buffered-file)
    11280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11286     # check output
    11287     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
    11288     (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")
    11289     # check that stop(1) was called
    11290     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
    11291     # don't restore from ebp
    11292     81 0/subop/add %esp 8/imm32
    11293     # . epilogue
    11294     5d/pop-to-ebp
    11295     c3/return
    11296
    11297 test-index-needs-offset-type:
    11298     # . prologue
    11299     55/push-ebp
    11300     89/<- %ebp 4/r32/esp
    11301     # setup
    11302     (clear-stream _test-input-stream)
    11303     (clear-stream $_test-input-buffered-file->buffer)
    11304     (clear-stream _test-output-stream)
    11305     (clear-stream $_test-output-buffered-file->buffer)
    11306     (clear-stream _test-error-stream)
    11307     (clear-stream $_test-error-buffered-file->buffer)
    11308     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11309     68/push 0/imm32
    11310     68/push 0/imm32
    11311     89/<- %edx 4/r32/esp
    11312     (tailor-exit-descriptor %edx 0x10)
    11313     #
    11314     (write _test-input-stream "fn foo {\n")
    11315     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
    11316     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
    11317     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11318     (write _test-input-stream "}\n")
    11319     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
    11320     (write _test-input-stream "  x: int\n")
    11321     (write _test-input-stream "  y: int\n")
    11322     (write _test-input-stream "  z: int\n")
    11323     (write _test-input-stream "}\n")
    11324     # convert
    11325     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11326     # registers except esp clobbered at this point
    11327     # restore ed
    11328     89/<- %edx 4/r32/esp
    11329     (flush _test-output-buffered-file)
    11330     (flush _test-error-buffered-file)
    11331 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11337     # check output
    11338     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
    11339     (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")
    11340     # check that stop(1) was called
    11341     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
    11342     # don't restore from ebp
    11343     81 0/subop/add %esp 8/imm32
    11344     # . epilogue
    11345     5d/pop-to-ebp
    11346     c3/return
    11347
    11348 test-index-with-output-not-address:
    11349     # . prologue
    11350     55/push-ebp
    11351     89/<- %ebp 4/r32/esp
    11352     # setup
    11353     (clear-stream _test-input-stream)
    11354     (clear-stream $_test-input-buffered-file->buffer)
    11355     (clear-stream _test-output-stream)
    11356     (clear-stream $_test-output-buffered-file->buffer)
    11357     (clear-stream _test-error-stream)
    11358     (clear-stream $_test-error-buffered-file->buffer)
    11359     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11360     68/push 0/imm32
    11361     68/push 0/imm32
    11362     89/<- %edx 4/r32/esp
    11363     (tailor-exit-descriptor %edx 0x10)
    11364     #
    11365     (write _test-input-stream "fn foo {\n")
    11366     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11367     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
    11368     (write _test-input-stream "}\n")
    11369     # convert
    11370     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11371     # registers except esp clobbered at this point
    11372     # restore ed
    11373     89/<- %edx 4/r32/esp
    11374     (flush _test-output-buffered-file)
    11375     (flush _test-error-buffered-file)
    11376 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11382     # check output
    11383     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
    11384     (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")
    11385     # check that stop(1) was called
    11386     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
    11387     # don't restore from ebp
    11388     81 0/subop/add %esp 8/imm32
    11389     # . epilogue
    11390     5d/pop-to-ebp
    11391     c3/return
    11392
    11393 test-index-with-output-not-address-2:
    11394     # . prologue
    11395     55/push-ebp
    11396     89/<- %ebp 4/r32/esp
    11397     # setup
    11398     (clear-stream _test-input-stream)
    11399     (clear-stream $_test-input-buffered-file->buffer)
    11400     (clear-stream _test-output-stream)
    11401     (clear-stream $_test-output-buffered-file->buffer)
    11402     (clear-stream _test-error-stream)
    11403     (clear-stream $_test-error-buffered-file->buffer)
    11404     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11405     68/push 0/imm32
    11406     68/push 0/imm32
    11407     89/<- %edx 4/r32/esp
    11408     (tailor-exit-descriptor %edx 0x10)
    11409     #
    11410     (write _test-input-stream "fn foo {\n")
    11411     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11412     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
    11413     (write _test-input-stream "}\n")
    11414     # convert
    11415     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11416     # registers except esp clobbered at this point
    11417     # restore ed
    11418     89/<- %edx 4/r32/esp
    11419     (flush _test-output-buffered-file)
    11420     (flush _test-error-buffered-file)
    11421 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11427     # check output
    11428     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
    11429     (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")
    11430     # check that stop(1) was called
    11431     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
    11432     # don't restore from ebp
    11433     81 0/subop/add %esp 8/imm32
    11434     # . epilogue
    11435     5d/pop-to-ebp
    11436     c3/return
    11437
    11438 test-index-with-wrong-output-type:
    11439     # . prologue
    11440     55/push-ebp
    11441     89/<- %ebp 4/r32/esp
    11442     # setup
    11443     (clear-stream _test-input-stream)
    11444     (clear-stream $_test-input-buffered-file->buffer)
    11445     (clear-stream _test-output-stream)
    11446     (clear-stream $_test-output-buffered-file->buffer)
    11447     (clear-stream _test-error-stream)
    11448     (clear-stream $_test-error-buffered-file->buffer)
    11449     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11450     68/push 0/imm32
    11451     68/push 0/imm32
    11452     89/<- %edx 4/r32/esp
    11453     (tailor-exit-descriptor %edx 0x10)
    11454     #
    11455     (write _test-input-stream "fn foo {\n")
    11456     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11457     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
    11458     (write _test-input-stream "}\n")
    11459     # convert
    11460     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11461     # registers except esp clobbered at this point
    11462     # restore ed
    11463     89/<- %edx 4/r32/esp
    11464     (flush _test-output-buffered-file)
    11465     (flush _test-error-buffered-file)
    11466 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11472     # check output
    11473     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
    11474     (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")
    11475     # check that stop(1) was called
    11476     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
    11477     # don't restore from ebp
    11478     81 0/subop/add %esp 8/imm32
    11479     # . epilogue
    11480     5d/pop-to-ebp
    11481     c3/return
    11482
    11483 test-index-with-wrong-output-compound-type:
    11484     # . prologue
    11485     55/push-ebp
    11486     89/<- %ebp 4/r32/esp
    11487     # setup
    11488     (clear-stream _test-input-stream)
    11489     (clear-stream $_test-input-buffered-file->buffer)
    11490     (clear-stream _test-output-stream)
    11491     (clear-stream $_test-output-buffered-file->buffer)
    11492     (clear-stream _test-error-stream)
    11493     (clear-stream $_test-error-buffered-file->buffer)
    11494     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11495     68/push 0/imm32
    11496     68/push 0/imm32
    11497     89/<- %edx 4/r32/esp
    11498     (tailor-exit-descriptor %edx 0x10)
    11499     #
    11500     (write _test-input-stream "fn foo {\n")
    11501     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    11502     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
    11503     (write _test-input-stream "}\n")
    11504     # convert
    11505     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11506     # registers except esp clobbered at this point
    11507     # restore ed
    11508     89/<- %edx 4/r32/esp
    11509     (flush _test-output-buffered-file)
    11510     (flush _test-error-buffered-file)
    11511 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11517     # check output
    11518     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
    11519     (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")
    11520     # check that stop(1) was called
    11521     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
    11522     # don't restore from ebp
    11523     81 0/subop/add %esp 8/imm32
    11524     # . epilogue
    11525     5d/pop-to-ebp
    11526     c3/return
    11527
    11528 test-index-with-no-inouts:
    11529     # . prologue
    11530     55/push-ebp
    11531     89/<- %ebp 4/r32/esp
    11532     # setup
    11533     (clear-stream _test-input-stream)
    11534     (clear-stream $_test-input-buffered-file->buffer)
    11535     (clear-stream _test-output-stream)
    11536     (clear-stream $_test-output-buffered-file->buffer)
    11537     (clear-stream _test-error-stream)
    11538     (clear-stream $_test-error-buffered-file->buffer)
    11539     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11540     68/push 0/imm32
    11541     68/push 0/imm32
    11542     89/<- %edx 4/r32/esp
    11543     (tailor-exit-descriptor %edx 0x10)
    11544     #
    11545     (write _test-input-stream "fn foo {\n")
    11546     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
    11547     (write _test-input-stream "}\n")
    11548     # convert
    11549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11550     # registers except esp clobbered at this point
    11551     # restore ed
    11552     89/<- %edx 4/r32/esp
    11553     (flush _test-output-buffered-file)
    11554     (flush _test-error-buffered-file)
    11555 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11561     # check output
    11562     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
    11563     (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")
    11564     # check that stop(1) was called
    11565     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
    11566     # don't restore from ebp
    11567     81 0/subop/add %esp 8/imm32
    11568     # . epilogue
    11569     5d/pop-to-ebp
    11570     c3/return
    11571
    11572 test-index-with-too-few-inouts:
    11573     # . prologue
    11574     55/push-ebp
    11575     89/<- %ebp 4/r32/esp
    11576     # setup
    11577     (clear-stream _test-input-stream)
    11578     (clear-stream $_test-input-buffered-file->buffer)
    11579     (clear-stream _test-output-stream)
    11580     (clear-stream $_test-output-buffered-file->buffer)
    11581     (clear-stream _test-error-stream)
    11582     (clear-stream $_test-error-buffered-file->buffer)
    11583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11584     68/push 0/imm32
    11585     68/push 0/imm32
    11586     89/<- %edx 4/r32/esp
    11587     (tailor-exit-descriptor %edx 0x10)
    11588     #
    11589     (write _test-input-stream "fn foo {\n")
    11590     (write _test-input-stream "  var a: (array int 3)\n")
    11591     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
    11592     (write _test-input-stream "}\n")
    11593     # convert
    11594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11595     # registers except esp clobbered at this point
    11596     # restore ed
    11597     89/<- %edx 4/r32/esp
    11598     (flush _test-output-buffered-file)
    11599     (flush _test-error-buffered-file)
    11600 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11606     # check output
    11607     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
    11608     (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")
    11609     # check that stop(1) was called
    11610     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
    11611     # don't restore from ebp
    11612     81 0/subop/add %esp 8/imm32
    11613     # . epilogue
    11614     5d/pop-to-ebp
    11615     c3/return
    11616
    11617 test-index-with-too-many-inouts:
    11618     # . prologue
    11619     55/push-ebp
    11620     89/<- %ebp 4/r32/esp
    11621     # setup
    11622     (clear-stream _test-input-stream)
    11623     (clear-stream $_test-input-buffered-file->buffer)
    11624     (clear-stream _test-output-stream)
    11625     (clear-stream $_test-output-buffered-file->buffer)
    11626     (clear-stream _test-error-stream)
    11627     (clear-stream $_test-error-buffered-file->buffer)
    11628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11629     68/push 0/imm32
    11630     68/push 0/imm32
    11631     89/<- %edx 4/r32/esp
    11632     (tailor-exit-descriptor %edx 0x10)
    11633     #
    11634     (write _test-input-stream "fn foo {\n")
    11635     (write _test-input-stream "  var a: (array int 3)\n")
    11636     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
    11637     (write _test-input-stream "}\n")
    11638     # convert
    11639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11640     # registers except esp clobbered at this point
    11641     # restore ed
    11642     89/<- %edx 4/r32/esp
    11643     (flush _test-output-buffered-file)
    11644     (flush _test-error-buffered-file)
    11645 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11651     # check output
    11652     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
    11653     (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")
    11654     # check that stop(1) was called
    11655     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
    11656     # don't restore from ebp
    11657     81 0/subop/add %esp 8/imm32
    11658     # . epilogue
    11659     5d/pop-to-ebp
    11660     c3/return
    11661
    11662 test-index-with-no-output:
    11663     # . prologue
    11664     55/push-ebp
    11665     89/<- %ebp 4/r32/esp
    11666     # setup
    11667     (clear-stream _test-input-stream)
    11668     (clear-stream $_test-input-buffered-file->buffer)
    11669     (clear-stream _test-output-stream)
    11670     (clear-stream $_test-output-buffered-file->buffer)
    11671     (clear-stream _test-error-stream)
    11672     (clear-stream $_test-error-buffered-file->buffer)
    11673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11674     68/push 0/imm32
    11675     68/push 0/imm32
    11676     89/<- %edx 4/r32/esp
    11677     (tailor-exit-descriptor %edx 0x10)
    11678     #
    11679     (write _test-input-stream "fn foo {\n")
    11680     (write _test-input-stream "  var a: (array int 3)\n")
    11681     (write _test-input-stream "  index a, 0\n")
    11682     (write _test-input-stream "}\n")
    11683     # convert
    11684     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11685     # registers except esp clobbered at this point
    11686     # restore ed
    11687     89/<- %edx 4/r32/esp
    11688     (flush _test-output-buffered-file)
    11689     (flush _test-error-buffered-file)
    11690 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11696     # check output
    11697     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
    11698     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
    11699     # check that stop(1) was called
    11700     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
    11701     # don't restore from ebp
    11702     81 0/subop/add %esp 8/imm32
    11703     # . epilogue
    11704     5d/pop-to-ebp
    11705     c3/return
    11706
    11707 test-index-with-too-many-outputs:
    11708     # . prologue
    11709     55/push-ebp
    11710     89/<- %ebp 4/r32/esp
    11711     # setup
    11712     (clear-stream _test-input-stream)
    11713     (clear-stream $_test-input-buffered-file->buffer)
    11714     (clear-stream _test-output-stream)
    11715     (clear-stream $_test-output-buffered-file->buffer)
    11716     (clear-stream _test-error-stream)
    11717     (clear-stream $_test-error-buffered-file->buffer)
    11718     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11719     68/push 0/imm32
    11720     68/push 0/imm32
    11721     89/<- %edx 4/r32/esp
    11722     (tailor-exit-descriptor %edx 0x10)
    11723     #
    11724     (write _test-input-stream "fn foo {\n")
    11725     (write _test-input-stream "  var a: (array int 3)\n")
    11726     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    11727     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    11728     (write _test-input-stream "  b, c <- 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-too-many-outputs: output should be empty")
    11745     (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")
    11746     # check that stop(1) was called
    11747     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: 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-compute-offset-with-non-array-atom-base-type:
    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: int\n")
    11773     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11774     (write _test-input-stream "}\n")
    11775     # convert
    11776     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11777     # registers except esp clobbered at this point
    11778     # restore ed
    11779     89/<- %edx 4/r32/esp
    11780     (flush _test-output-buffered-file)
    11781     (flush _test-error-buffered-file)
    11782 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11788     # check output
    11789     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
    11790     (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")
    11791     # check that stop(1) was called
    11792     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
    11793     # don't restore from ebp
    11794     81 0/subop/add %esp 8/imm32
    11795     # . epilogue
    11796     5d/pop-to-ebp
    11797     c3/return
    11798
    11799 test-compute-offset-with-non-array-compound-base-type:
    11800     # . prologue
    11801     55/push-ebp
    11802     89/<- %ebp 4/r32/esp
    11803     # setup
    11804     (clear-stream _test-input-stream)
    11805     (clear-stream $_test-input-buffered-file->buffer)
    11806     (clear-stream _test-output-stream)
    11807     (clear-stream $_test-output-buffered-file->buffer)
    11808     (clear-stream _test-error-stream)
    11809     (clear-stream $_test-error-buffered-file->buffer)
    11810     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11811     68/push 0/imm32
    11812     68/push 0/imm32
    11813     89/<- %edx 4/r32/esp
    11814     (tailor-exit-descriptor %edx 0x10)
    11815     #
    11816     (write _test-input-stream "fn foo {\n")
    11817     (write _test-input-stream "  var a: (handle int)\n")
    11818     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11819     (write _test-input-stream "}\n")
    11820     # convert
    11821     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11822     # registers except esp clobbered at this point
    11823     # restore ed
    11824     89/<- %edx 4/r32/esp
    11825     (flush _test-output-buffered-file)
    11826     (flush _test-error-buffered-file)
    11827 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11833     # check output
    11834     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
    11835     (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")
    11836     # check that stop(1) was called
    11837     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
    11838     # don't restore from ebp
    11839     81 0/subop/add %esp 8/imm32
    11840     # . epilogue
    11841     5d/pop-to-ebp
    11842     c3/return
    11843
    11844 test-compute-offset-with-non-array-compound-base-type-2:
    11845     # . prologue
    11846     55/push-ebp
    11847     89/<- %ebp 4/r32/esp
    11848     # setup
    11849     (clear-stream _test-input-stream)
    11850     (clear-stream $_test-input-buffered-file->buffer)
    11851     (clear-stream _test-output-stream)
    11852     (clear-stream $_test-output-buffered-file->buffer)
    11853     (clear-stream _test-error-stream)
    11854     (clear-stream $_test-error-buffered-file->buffer)
    11855     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11856     68/push 0/imm32
    11857     68/push 0/imm32
    11858     89/<- %edx 4/r32/esp
    11859     (tailor-exit-descriptor %edx 0x10)
    11860     #
    11861     (write _test-input-stream "fn foo {\n")
    11862     (write _test-input-stream "  var a: (addr int)\n")
    11863     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11864     (write _test-input-stream "}\n")
    11865     # convert
    11866     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11867     # registers except esp clobbered at this point
    11868     # restore ed
    11869     89/<- %edx 4/r32/esp
    11870     (flush _test-output-buffered-file)
    11871     (flush _test-error-buffered-file)
    11872 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11878     # check output
    11879     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
    11880     (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")
    11881     # check that stop(1) was called
    11882     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
    11883     # don't restore from ebp
    11884     81 0/subop/add %esp 8/imm32
    11885     # . epilogue
    11886     5d/pop-to-ebp
    11887     c3/return
    11888
    11889 test-compute-offset-with-array-atom-base-type:
    11890     # . prologue
    11891     55/push-ebp
    11892     89/<- %ebp 4/r32/esp
    11893     # setup
    11894     (clear-stream _test-input-stream)
    11895     (clear-stream $_test-input-buffered-file->buffer)
    11896     (clear-stream _test-output-stream)
    11897     (clear-stream $_test-output-buffered-file->buffer)
    11898     (clear-stream _test-error-stream)
    11899     (clear-stream $_test-error-buffered-file->buffer)
    11900     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11901     68/push 0/imm32
    11902     68/push 0/imm32
    11903     89/<- %edx 4/r32/esp
    11904     (tailor-exit-descriptor %edx 0x10)
    11905     #
    11906     (write _test-input-stream "fn foo {\n")
    11907     (write _test-input-stream "  var a: array\n")
    11908     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11909     (write _test-input-stream "}\n")
    11910     # convert
    11911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11912     # registers except esp clobbered at this point
    11913     # restore ed
    11914     89/<- %edx 4/r32/esp
    11915     (flush _test-output-buffered-file)
    11916     (flush _test-error-buffered-file)
    11917 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11923     # check output
    11924     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
    11925     (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")
    11926     # check that stop(1) was called
    11927     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
    11928     # don't restore from ebp
    11929     81 0/subop/add %esp 8/imm32
    11930     # . epilogue
    11931     5d/pop-to-ebp
    11932     c3/return
    11933
    11934 test-compute-offset-with-wrong-index-type:
    11935     # . prologue
    11936     55/push-ebp
    11937     89/<- %ebp 4/r32/esp
    11938     # setup
    11939     (clear-stream _test-input-stream)
    11940     (clear-stream $_test-input-buffered-file->buffer)
    11941     (clear-stream _test-output-stream)
    11942     (clear-stream $_test-output-buffered-file->buffer)
    11943     (clear-stream _test-error-stream)
    11944     (clear-stream $_test-error-buffered-file->buffer)
    11945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11946     68/push 0/imm32
    11947     68/push 0/imm32
    11948     89/<- %edx 4/r32/esp
    11949     (tailor-exit-descriptor %edx 0x10)
    11950     #
    11951     (write _test-input-stream "fn foo {\n")
    11952     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11953     (write _test-input-stream "  var b: boolean\n")
    11954     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
    11955     (write _test-input-stream "}\n")
    11956     # convert
    11957     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11958     # registers except esp clobbered at this point
    11959     # restore ed
    11960     89/<- %edx 4/r32/esp
    11961     (flush _test-output-buffered-file)
    11962     (flush _test-error-buffered-file)
    11963 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11969     # check output
    11970     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
    11971     (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")
    11972     # check that stop(1) was called
    11973     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
    11974     # don't restore from ebp
    11975     81 0/subop/add %esp 8/imm32
    11976     # . epilogue
    11977     5d/pop-to-ebp
    11978     c3/return
    11979
    11980 test-compute-offset-with-output-not-offset:
    11981     # . prologue
    11982     55/push-ebp
    11983     89/<- %ebp 4/r32/esp
    11984     # setup
    11985     (clear-stream _test-input-stream)
    11986     (clear-stream $_test-input-buffered-file->buffer)
    11987     (clear-stream _test-output-stream)
    11988     (clear-stream $_test-output-buffered-file->buffer)
    11989     (clear-stream _test-error-stream)
    11990     (clear-stream $_test-error-buffered-file->buffer)
    11991     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11992     68/push 0/imm32
    11993     68/push 0/imm32
    11994     89/<- %edx 4/r32/esp
    11995     (tailor-exit-descriptor %edx 0x10)
    11996     #
    11997     (write _test-input-stream "fn foo {\n")
    11998     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11999     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
    12000     (write _test-input-stream "}\n")
    12001     # convert
    12002     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12003     # registers except esp clobbered at this point
    12004     # restore ed
    12005     89/<- %edx 4/r32/esp
    12006     (flush _test-output-buffered-file)
    12007     (flush _test-error-buffered-file)
    12008 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12014     # check output
    12015     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
    12016     (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")
    12017     # check that stop(1) was called
    12018     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
    12019     # don't restore from ebp
    12020     81 0/subop/add %esp 8/imm32
    12021     # . epilogue
    12022     5d/pop-to-ebp
    12023     c3/return
    12024
    12025 test-compute-offset-with-output-not-address-2:
    12026     # . prologue
    12027     55/push-ebp
    12028     89/<- %ebp 4/r32/esp
    12029     # setup
    12030     (clear-stream _test-input-stream)
    12031     (clear-stream $_test-input-buffered-file->buffer)
    12032     (clear-stream _test-output-stream)
    12033     (clear-stream $_test-output-buffered-file->buffer)
    12034     (clear-stream _test-error-stream)
    12035     (clear-stream $_test-error-buffered-file->buffer)
    12036     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12037     68/push 0/imm32
    12038     68/push 0/imm32
    12039     89/<- %edx 4/r32/esp
    12040     (tailor-exit-descriptor %edx 0x10)
    12041     #
    12042     (write _test-input-stream "fn foo {\n")
    12043     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12044     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
    12045     (write _test-input-stream "}\n")
    12046     # convert
    12047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12048     # registers except esp clobbered at this point
    12049     # restore ed
    12050     89/<- %edx 4/r32/esp
    12051     (flush _test-output-buffered-file)
    12052     (flush _test-error-buffered-file)
    12053 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12059     # check output
    12060     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
    12061     (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")
    12062     # check that stop(1) was called
    12063     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
    12064     # don't restore from ebp
    12065     81 0/subop/add %esp 8/imm32
    12066     # . epilogue
    12067     5d/pop-to-ebp
    12068     c3/return
    12069
    12070 test-compute-offset-with-wrong-output-type:
    12071     # . prologue
    12072     55/push-ebp
    12073     89/<- %ebp 4/r32/esp
    12074     # setup
    12075     (clear-stream _test-input-stream)
    12076     (clear-stream $_test-input-buffered-file->buffer)
    12077     (clear-stream _test-output-stream)
    12078     (clear-stream $_test-output-buffered-file->buffer)
    12079     (clear-stream _test-error-stream)
    12080     (clear-stream $_test-error-buffered-file->buffer)
    12081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12082     68/push 0/imm32
    12083     68/push 0/imm32
    12084     89/<- %edx 4/r32/esp
    12085     (tailor-exit-descriptor %edx 0x10)
    12086     #
    12087     (write _test-input-stream "fn foo {\n")
    12088     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12089     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
    12090     (write _test-input-stream "}\n")
    12091     # convert
    12092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12093     # registers except esp clobbered at this point
    12094     # restore ed
    12095     89/<- %edx 4/r32/esp
    12096     (flush _test-output-buffered-file)
    12097     (flush _test-error-buffered-file)
    12098 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12104     # check output
    12105     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
    12106     (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")
    12107     # check that stop(1) was called
    12108     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
    12109     # don't restore from ebp
    12110     81 0/subop/add %esp 8/imm32
    12111     # . epilogue
    12112     5d/pop-to-ebp
    12113     c3/return
    12114
    12115 test-compute-offset-with-wrong-output-compound-type:
    12116     # . prologue
    12117     55/push-ebp
    12118     89/<- %ebp 4/r32/esp
    12119     # setup
    12120     (clear-stream _test-input-stream)
    12121     (clear-stream $_test-input-buffered-file->buffer)
    12122     (clear-stream _test-output-stream)
    12123     (clear-stream $_test-output-buffered-file->buffer)
    12124     (clear-stream _test-error-stream)
    12125     (clear-stream $_test-error-buffered-file->buffer)
    12126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12127     68/push 0/imm32
    12128     68/push 0/imm32
    12129     89/<- %edx 4/r32/esp
    12130     (tailor-exit-descriptor %edx 0x10)
    12131     #
    12132     (write _test-input-stream "fn foo {\n")
    12133     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    12134     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
    12135     (write _test-input-stream "}\n")
    12136     # convert
    12137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12138     # registers except esp clobbered at this point
    12139     # restore ed
    12140     89/<- %edx 4/r32/esp
    12141     (flush _test-output-buffered-file)
    12142     (flush _test-error-buffered-file)
    12143 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12149     # check output
    12150     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
    12151     (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")
    12152     # check that stop(1) was called
    12153     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
    12154     # don't restore from ebp
    12155     81 0/subop/add %esp 8/imm32
    12156     # . epilogue
    12157     5d/pop-to-ebp
    12158     c3/return
    12159
    12160 test-compute-offset-with-no-inouts:
    12161     # . prologue
    12162     55/push-ebp
    12163     89/<- %ebp 4/r32/esp
    12164     # setup
    12165     (clear-stream _test-input-stream)
    12166     (clear-stream $_test-input-buffered-file->buffer)
    12167     (clear-stream _test-output-stream)
    12168     (clear-stream $_test-output-buffered-file->buffer)
    12169     (clear-stream _test-error-stream)
    12170     (clear-stream $_test-error-buffered-file->buffer)
    12171     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12172     68/push 0/imm32
    12173     68/push 0/imm32
    12174     89/<- %edx 4/r32/esp
    12175     (tailor-exit-descriptor %edx 0x10)
    12176     #
    12177     (write _test-input-stream "fn foo {\n")
    12178     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
    12179     (write _test-input-stream "}\n")
    12180     # convert
    12181     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12182     # registers except esp clobbered at this point
    12183     # restore ed
    12184     89/<- %edx 4/r32/esp
    12185     (flush _test-output-buffered-file)
    12186     (flush _test-error-buffered-file)
    12187 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12193     # check output
    12194     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
    12195     (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")
    12196     # check that stop(1) was called
    12197     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
    12198     # don't restore from ebp
    12199     81 0/subop/add %esp 8/imm32
    12200     # . epilogue
    12201     5d/pop-to-ebp
    12202     c3/return
    12203
    12204 test-compute-offset-with-too-few-inouts:
    12205     # . prologue
    12206     55/push-ebp
    12207     89/<- %ebp 4/r32/esp
    12208     # setup
    12209     (clear-stream _test-input-stream)
    12210     (clear-stream $_test-input-buffered-file->buffer)
    12211     (clear-stream _test-output-stream)
    12212     (clear-stream $_test-output-buffered-file->buffer)
    12213     (clear-stream _test-error-stream)
    12214     (clear-stream $_test-error-buffered-file->buffer)
    12215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12216     68/push 0/imm32
    12217     68/push 0/imm32
    12218     89/<- %edx 4/r32/esp
    12219     (tailor-exit-descriptor %edx 0x10)
    12220     #
    12221     (write _test-input-stream "fn foo {\n")
    12222     (write _test-input-stream "  var a: (array int 3)\n")
    12223     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
    12224     (write _test-input-stream "}\n")
    12225     # convert
    12226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12227     # registers except esp clobbered at this point
    12228     # restore ed
    12229     89/<- %edx 4/r32/esp
    12230     (flush _test-output-buffered-file)
    12231     (flush _test-error-buffered-file)
    12232 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12238     # check output
    12239     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
    12240     (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")
    12241     # check that stop(1) was called
    12242     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
    12243     # don't restore from ebp
    12244     81 0/subop/add %esp 8/imm32
    12245     # . epilogue
    12246     5d/pop-to-ebp
    12247     c3/return
    12248
    12249 test-compute-offset-with-too-many-inouts:
    12250     # . prologue
    12251     55/push-ebp
    12252     89/<- %ebp 4/r32/esp
    12253     # setup
    12254     (clear-stream _test-input-stream)
    12255     (clear-stream $_test-input-buffered-file->buffer)
    12256     (clear-stream _test-output-stream)
    12257     (clear-stream $_test-output-buffered-file->buffer)
    12258     (clear-stream _test-error-stream)
    12259     (clear-stream $_test-error-buffered-file->buffer)
    12260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12261     68/push 0/imm32
    12262     68/push 0/imm32
    12263     89/<- %edx 4/r32/esp
    12264     (tailor-exit-descriptor %edx 0x10)
    12265     #
    12266     (write _test-input-stream "fn foo {\n")
    12267     (write _test-input-stream "  var a: (array int 3)\n")
    12268     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
    12269     (write _test-input-stream "}\n")
    12270     # convert
    12271     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12272     # registers except esp clobbered at this point
    12273     # restore ed
    12274     89/<- %edx 4/r32/esp
    12275     (flush _test-output-buffered-file)
    12276     (flush _test-error-buffered-file)
    12277 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12283     # check output
    12284     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
    12285     (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")
    12286     # check that stop(1) was called
    12287     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
    12288     # don't restore from ebp
    12289     81 0/subop/add %esp 8/imm32
    12290     # . epilogue
    12291     5d/pop-to-ebp
    12292     c3/return
    12293
    12294 test-compute-offset-with-no-output:
    12295     # . prologue
    12296     55/push-ebp
    12297     89/<- %ebp 4/r32/esp
    12298     # setup
    12299     (clear-stream _test-input-stream)
    12300     (clear-stream $_test-input-buffered-file->buffer)
    12301     (clear-stream _test-output-stream)
    12302     (clear-stream $_test-output-buffered-file->buffer)
    12303     (clear-stream _test-error-stream)
    12304     (clear-stream $_test-error-buffered-file->buffer)
    12305     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12306     68/push 0/imm32
    12307     68/push 0/imm32
    12308     89/<- %edx 4/r32/esp
    12309     (tailor-exit-descriptor %edx 0x10)
    12310     #
    12311     (write _test-input-stream "fn foo {\n")
    12312     (write _test-input-stream "  var a: (array int 3)\n")
    12313     (write _test-input-stream "  compute-offset a, 0\n")
    12314     (write _test-input-stream "}\n")
    12315     # convert
    12316     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12317     # registers except esp clobbered at this point
    12318     # restore ed
    12319     89/<- %edx 4/r32/esp
    12320     (flush _test-output-buffered-file)
    12321     (flush _test-error-buffered-file)
    12322 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12328     # check output
    12329     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
    12330     (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")
    12331     # check that stop(1) was called
    12332     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
    12333     # don't restore from ebp
    12334     81 0/subop/add %esp 8/imm32
    12335     # . epilogue
    12336     5d/pop-to-ebp
    12337     c3/return
    12338
    12339 test-compute-offset-with-too-many-outputs:
    12340     # . prologue
    12341     55/push-ebp
    12342     89/<- %ebp 4/r32/esp
    12343     # setup
    12344     (clear-stream _test-input-stream)
    12345     (clear-stream $_test-input-buffered-file->buffer)
    12346     (clear-stream _test-output-stream)
    12347     (clear-stream $_test-output-buffered-file->buffer)
    12348     (clear-stream _test-error-stream)
    12349     (clear-stream $_test-error-buffered-file->buffer)
    12350     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12351     68/push 0/imm32
    12352     68/push 0/imm32
    12353     89/<- %edx 4/r32/esp
    12354     (tailor-exit-descriptor %edx 0x10)
    12355     #
    12356     (write _test-input-stream "fn foo {\n")
    12357     (write _test-input-stream "  var a: (array int 3)\n")
    12358     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
    12359     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    12360     (write _test-input-stream "  b, c <- 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-too-many-outputs: output should be empty")
    12377     (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")
    12378     # check that stop(1) was called
    12379     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: 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-convert-read-from-stream:
    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     #
    12396     (write _test-input-stream "fn foo {\n")
    12397     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12398     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12399     (write _test-input-stream "  read-from-stream s, o\n")
    12400     (write _test-input-stream "}\n")
    12401     # convert
    12402     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12403     # registers except esp clobbered at this point
    12404     # restore ed
    12405     89/<- %edx 4/r32/esp
    12406     (flush _test-output-buffered-file)
    12407     (flush _test-error-buffered-file)
    12408 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12414     # check output
    12415     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
    12416     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
    12417     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
    12418     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
    12419     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
    12420     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
    12421     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
    12422     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
    12423     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
    12424     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
    12425     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
    12426     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
    12427     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
    12428     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
    12429     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
    12430     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
    12431     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
    12432     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
    12433     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
    12434     # . epilogue
    12435     89/<- %esp 5/r32/ebp
    12436     5d/pop-to-ebp
    12437     c3/return
    12438
    12439 test-convert-read-from-stream-with-correct-payload-size:
    12440     # . prologue
    12441     55/push-ebp
    12442     89/<- %ebp 4/r32/esp
    12443     # setup
    12444     (clear-stream _test-input-stream)
    12445     (clear-stream $_test-input-buffered-file->buffer)
    12446     (clear-stream _test-output-stream)
    12447     (clear-stream $_test-output-buffered-file->buffer)
    12448     #
    12449     (write _test-input-stream "fn foo {\n")
    12450     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12451     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12452     (write _test-input-stream "  read-from-stream s, o\n")
    12453     (write _test-input-stream "}\n")
    12454     # convert
    12455     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12456     # registers except esp clobbered at this point
    12457     # restore ed
    12458     89/<- %edx 4/r32/esp
    12459     (flush _test-output-buffered-file)
    12460     (flush _test-error-buffered-file)
    12461 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12467     # check output
    12468     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
    12469     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
    12470     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
    12471     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
    12472     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
    12473     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
    12474     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
    12475     (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")
    12476     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
    12477     (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")
    12478     (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")
    12479     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
    12480     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
    12481     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
    12482     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
    12483     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
    12484     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
    12485     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
    12486     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
    12487     # . epilogue
    12488     89/<- %esp 5/r32/ebp
    12489     5d/pop-to-ebp
    12490     c3/return
    12491
    12492 test-read-from-stream-with-non-stream-atom-base-type:
    12493     # . prologue
    12494     55/push-ebp
    12495     89/<- %ebp 4/r32/esp
    12496     # setup
    12497     (clear-stream _test-input-stream)
    12498     (clear-stream $_test-input-buffered-file->buffer)
    12499     (clear-stream _test-output-stream)
    12500     (clear-stream $_test-output-buffered-file->buffer)
    12501     (clear-stream _test-error-stream)
    12502     (clear-stream $_test-error-buffered-file->buffer)
    12503     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12504     68/push 0/imm32
    12505     68/push 0/imm32
    12506     89/<- %edx 4/r32/esp
    12507     (tailor-exit-descriptor %edx 0x10)
    12508     #
    12509     (write _test-input-stream "fn foo {\n")
    12510     (write _test-input-stream "  var a: int\n")
    12511     (write _test-input-stream "  read-from-stream a, 0\n")
    12512     (write _test-input-stream "}\n")
    12513     # convert
    12514     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12515     # registers except esp clobbered at this point
    12516     # restore ed
    12517     89/<- %edx 4/r32/esp
    12518     (flush _test-output-buffered-file)
    12519     (flush _test-error-buffered-file)
    12520 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12526     # check output
    12527     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
    12528     (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")
    12529     # check that stop(1) was called
    12530     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
    12531     # don't restore from ebp
    12532     81 0/subop/add %esp 8/imm32
    12533     # . epilogue
    12534     5d/pop-to-ebp
    12535     c3/return
    12536
    12537 test-read-from-stream-with-non-stream-compound-base-type:
    12538     # . prologue
    12539     55/push-ebp
    12540     89/<- %ebp 4/r32/esp
    12541     # setup
    12542     (clear-stream _test-input-stream)
    12543     (clear-stream $_test-input-buffered-file->buffer)
    12544     (clear-stream _test-output-stream)
    12545     (clear-stream $_test-output-buffered-file->buffer)
    12546     (clear-stream _test-error-stream)
    12547     (clear-stream $_test-error-buffered-file->buffer)
    12548     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12549     68/push 0/imm32
    12550     68/push 0/imm32
    12551     89/<- %edx 4/r32/esp
    12552     (tailor-exit-descriptor %edx 0x10)
    12553     #
    12554     (write _test-input-stream "fn foo {\n")
    12555     (write _test-input-stream "  var a: (handle int)\n")
    12556     (write _test-input-stream "  read-from-stream a, 0\n")
    12557     (write _test-input-stream "}\n")
    12558     # convert
    12559     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12560     # registers except esp clobbered at this point
    12561     # restore ed
    12562     89/<- %edx 4/r32/esp
    12563     (flush _test-output-buffered-file)
    12564     (flush _test-error-buffered-file)
    12565 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12571     # check output
    12572     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
    12573     (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")
    12574     # check that stop(1) was called
    12575     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
    12576     # don't restore from ebp
    12577     81 0/subop/add %esp 8/imm32
    12578     # . epilogue
    12579     5d/pop-to-ebp
    12580     c3/return
    12581
    12582 test-read-from-stream-with-non-stream-compound-base-type-2:
    12583     # . prologue
    12584     55/push-ebp
    12585     89/<- %ebp 4/r32/esp
    12586     # setup
    12587     (clear-stream _test-input-stream)
    12588     (clear-stream $_test-input-buffered-file->buffer)
    12589     (clear-stream _test-output-stream)
    12590     (clear-stream $_test-output-buffered-file->buffer)
    12591     (clear-stream _test-error-stream)
    12592     (clear-stream $_test-error-buffered-file->buffer)
    12593     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12594     68/push 0/imm32
    12595     68/push 0/imm32
    12596     89/<- %edx 4/r32/esp
    12597     (tailor-exit-descriptor %edx 0x10)
    12598     #
    12599     (write _test-input-stream "fn foo {\n")
    12600     (write _test-input-stream "  var a: (addr int)\n")
    12601     (write _test-input-stream "  read-from-stream a, 0\n")
    12602     (write _test-input-stream "}\n")
    12603     # convert
    12604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12605     # registers except esp clobbered at this point
    12606     # restore ed
    12607     89/<- %edx 4/r32/esp
    12608     (flush _test-output-buffered-file)
    12609     (flush _test-error-buffered-file)
    12610 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12616     # check output
    12617     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
    12618     (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")
    12619     # check that stop(1) was called
    12620     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
    12621     # don't restore from ebp
    12622     81 0/subop/add %esp 8/imm32
    12623     # . epilogue
    12624     5d/pop-to-ebp
    12625     c3/return
    12626
    12627 test-read-from-stream-with-stream-atom-base-type:
    12628     # . prologue
    12629     55/push-ebp
    12630     89/<- %ebp 4/r32/esp
    12631     # setup
    12632     (clear-stream _test-input-stream)
    12633     (clear-stream $_test-input-buffered-file->buffer)
    12634     (clear-stream _test-output-stream)
    12635     (clear-stream $_test-output-buffered-file->buffer)
    12636     (clear-stream _test-error-stream)
    12637     (clear-stream $_test-error-buffered-file->buffer)
    12638     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12639     68/push 0/imm32
    12640     68/push 0/imm32
    12641     89/<- %edx 4/r32/esp
    12642     (tailor-exit-descriptor %edx 0x10)
    12643     #
    12644     (write _test-input-stream "fn foo {\n")
    12645     (write _test-input-stream "  var a: stream\n")
    12646     (write _test-input-stream "  read-from-stream a, 0\n")
    12647     (write _test-input-stream "}\n")
    12648     # convert
    12649     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12650     # registers except esp clobbered at this point
    12651     # restore ed
    12652     89/<- %edx 4/r32/esp
    12653     (flush _test-output-buffered-file)
    12654     (flush _test-error-buffered-file)
    12655 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12661     # check output
    12662     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
    12663     (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")
    12664     # check that stop(1) was called
    12665     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
    12666     # don't restore from ebp
    12667     81 0/subop/add %esp 8/imm32
    12668     # . epilogue
    12669     5d/pop-to-ebp
    12670     c3/return
    12671
    12672 test-read-from-stream-with-wrong-index-type:
    12673     # . prologue
    12674     55/push-ebp
    12675     89/<- %ebp 4/r32/esp
    12676     # setup
    12677     (clear-stream _test-input-stream)
    12678     (clear-stream $_test-input-buffered-file->buffer)
    12679     (clear-stream _test-output-stream)
    12680     (clear-stream $_test-output-buffered-file->buffer)
    12681     (clear-stream _test-error-stream)
    12682     (clear-stream $_test-error-buffered-file->buffer)
    12683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12684     68/push 0/imm32
    12685     68/push 0/imm32
    12686     89/<- %edx 4/r32/esp
    12687     (tailor-exit-descriptor %edx 0x10)
    12688     #
    12689     (write _test-input-stream "fn foo {\n")
    12690     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    12691     (write _test-input-stream "  var b: boolean\n")
    12692     (write _test-input-stream "  read-from-stream a, b\n")
    12693     (write _test-input-stream "}\n")
    12694     # convert
    12695     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12696     # registers except esp clobbered at this point
    12697     # restore ed
    12698     89/<- %edx 4/r32/esp
    12699     (flush _test-output-buffered-file)
    12700     (flush _test-error-buffered-file)
    12701 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12707     # check output
    12708     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
    12709     (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")
    12710     # check that stop(1) was called
    12711     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
    12712     # don't restore from ebp
    12713     81 0/subop/add %esp 8/imm32
    12714     # . epilogue
    12715     5d/pop-to-ebp
    12716     c3/return
    12717
    12718 test-read-from-stream-with-no-inouts:
    12719     # . prologue
    12720     55/push-ebp
    12721     89/<- %ebp 4/r32/esp
    12722     # setup
    12723     (clear-stream _test-input-stream)
    12724     (clear-stream $_test-input-buffered-file->buffer)
    12725     (clear-stream _test-output-stream)
    12726     (clear-stream $_test-output-buffered-file->buffer)
    12727     (clear-stream _test-error-stream)
    12728     (clear-stream $_test-error-buffered-file->buffer)
    12729     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12730     68/push 0/imm32
    12731     68/push 0/imm32
    12732     89/<- %edx 4/r32/esp
    12733     (tailor-exit-descriptor %edx 0x10)
    12734     #
    12735     (write _test-input-stream "fn foo {\n")
    12736     (write _test-input-stream "  read-from-stream\n")
    12737     (write _test-input-stream "}\n")
    12738     # convert
    12739     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12740     # registers except esp clobbered at this point
    12741     # restore ed
    12742     89/<- %edx 4/r32/esp
    12743     (flush _test-output-buffered-file)
    12744     (flush _test-error-buffered-file)
    12745 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12751     # check output
    12752     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
    12753     (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")
    12754     # check that stop(1) was called
    12755     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
    12756     # don't restore from ebp
    12757     81 0/subop/add %esp 8/imm32
    12758     # . epilogue
    12759     5d/pop-to-ebp
    12760     c3/return
    12761
    12762 test-read-from-stream-with-too-few-inouts:
    12763     # . prologue
    12764     55/push-ebp
    12765     89/<- %ebp 4/r32/esp
    12766     # setup
    12767     (clear-stream _test-input-stream)
    12768     (clear-stream $_test-input-buffered-file->buffer)
    12769     (clear-stream _test-output-stream)
    12770     (clear-stream $_test-output-buffered-file->buffer)
    12771     (clear-stream _test-error-stream)
    12772     (clear-stream $_test-error-buffered-file->buffer)
    12773     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12774     68/push 0/imm32
    12775     68/push 0/imm32
    12776     89/<- %edx 4/r32/esp
    12777     (tailor-exit-descriptor %edx 0x10)
    12778     #
    12779     (write _test-input-stream "fn foo {\n")
    12780     (write _test-input-stream "  var a: (addr stream int)\n")
    12781     (write _test-input-stream "  read-from-stream a\n")
    12782     (write _test-input-stream "}\n")
    12783     # convert
    12784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12785     # registers except esp clobbered at this point
    12786     # restore ed
    12787     89/<- %edx 4/r32/esp
    12788     (flush _test-output-buffered-file)
    12789     (flush _test-error-buffered-file)
    12790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12796     # check output
    12797     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
    12798     (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")
    12799     # check that stop(1) was called
    12800     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
    12801     # don't restore from ebp
    12802     81 0/subop/add %esp 8/imm32
    12803     # . epilogue
    12804     5d/pop-to-ebp
    12805     c3/return
    12806
    12807 test-read-from-stream-with-too-many-inouts:
    12808     # . prologue
    12809     55/push-ebp
    12810     89/<- %ebp 4/r32/esp
    12811     # setup
    12812     (clear-stream _test-input-stream)
    12813     (clear-stream $_test-input-buffered-file->buffer)
    12814     (clear-stream _test-output-stream)
    12815     (clear-stream $_test-output-buffered-file->buffer)
    12816     (clear-stream _test-error-stream)
    12817     (clear-stream $_test-error-buffered-file->buffer)
    12818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12819     68/push 0/imm32
    12820     68/push 0/imm32
    12821     89/<- %edx 4/r32/esp
    12822     (tailor-exit-descriptor %edx 0x10)
    12823     #
    12824     (write _test-input-stream "fn foo {\n")
    12825     (write _test-input-stream "  var a: (addr stream int)\n")
    12826     (write _test-input-stream "  var b: (addr int)\n")
    12827     (write _test-input-stream "  read-from-stream a, b, 0\n")
    12828     (write _test-input-stream "}\n")
    12829     # convert
    12830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12831     # registers except esp clobbered at this point
    12832     # restore ed
    12833     89/<- %edx 4/r32/esp
    12834     (flush _test-output-buffered-file)
    12835     (flush _test-error-buffered-file)
    12836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12842     # check output
    12843     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
    12844     (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")
    12845     # check that stop(1) was called
    12846     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
    12847     # don't restore from ebp
    12848     81 0/subop/add %esp 8/imm32
    12849     # . epilogue
    12850     5d/pop-to-ebp
    12851     c3/return
    12852
    12853 test-read-from-stream-with-output:
    12854     # . prologue
    12855     55/push-ebp
    12856     89/<- %ebp 4/r32/esp
    12857     # setup
    12858     (clear-stream _test-input-stream)
    12859     (clear-stream $_test-input-buffered-file->buffer)
    12860     (clear-stream _test-output-stream)
    12861     (clear-stream $_test-output-buffered-file->buffer)
    12862     (clear-stream _test-error-stream)
    12863     (clear-stream $_test-error-buffered-file->buffer)
    12864     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12865     68/push 0/imm32
    12866     68/push 0/imm32
    12867     89/<- %edx 4/r32/esp
    12868     (tailor-exit-descriptor %edx 0x10)
    12869     #
    12870     (write _test-input-stream "fn foo {\n")
    12871     (write _test-input-stream "  var a: (addr stream int)\n")
    12872     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    12873     (write _test-input-stream "  b <- read-from-stream a, b\n")
    12874     (write _test-input-stream "}\n")
    12875     # convert
    12876     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12877     # registers except esp clobbered at this point
    12878     # restore ed
    12879     89/<- %edx 4/r32/esp
    12880     (flush _test-output-buffered-file)
    12881     (flush _test-error-buffered-file)
    12882 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12888     # check output
    12889     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
    12890     (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")
    12891     # check that stop(1) was called
    12892     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
    12893     # don't restore from ebp
    12894     81 0/subop/add %esp 8/imm32
    12895     # . epilogue
    12896     5d/pop-to-ebp
    12897     c3/return
    12898
    12899 test-convert-write-to-stream:
    12900     # . prologue
    12901     55/push-ebp
    12902     89/<- %ebp 4/r32/esp
    12903     # setup
    12904     (clear-stream _test-input-stream)
    12905     (clear-stream $_test-input-buffered-file->buffer)
    12906     (clear-stream _test-output-stream)
    12907     (clear-stream $_test-output-buffered-file->buffer)
    12908     #
    12909     (write _test-input-stream "fn foo {\n")
    12910     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12911     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12912     (write _test-input-stream "  write-to-stream s, o\n")
    12913     (write _test-input-stream "}\n")
    12914     # convert
    12915     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12916     # registers except esp clobbered at this point
    12917     # restore ed
    12918     89/<- %edx 4/r32/esp
    12919     (flush _test-output-buffered-file)
    12920     (flush _test-error-buffered-file)
    12921 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12927     # check output
    12928     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
    12929     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
    12930     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
    12931     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
    12932     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
    12933     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
    12934     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
    12935     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
    12936     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
    12937     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
    12938     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
    12939     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
    12940     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
    12941     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
    12942     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
    12943     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
    12944     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
    12945     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
    12946     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
    12947     # . epilogue
    12948     89/<- %esp 5/r32/ebp
    12949     5d/pop-to-ebp
    12950     c3/return
    12951
    12952 test-convert-write-to-stream-with-correct-payload-size:
    12953     # . prologue
    12954     55/push-ebp
    12955     89/<- %ebp 4/r32/esp
    12956     # setup
    12957     (clear-stream _test-input-stream)
    12958     (clear-stream $_test-input-buffered-file->buffer)
    12959     (clear-stream _test-output-stream)
    12960     (clear-stream $_test-output-buffered-file->buffer)
    12961     #
    12962     (write _test-input-stream "fn foo {\n")
    12963     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12964     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12965     (write _test-input-stream "  write-to-stream s, o\n")
    12966     (write _test-input-stream "}\n")
    12967     # convert
    12968     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12969     # registers except esp clobbered at this point
    12970     # restore ed
    12971     89/<- %edx 4/r32/esp
    12972     (flush _test-output-buffered-file)
    12973     (flush _test-error-buffered-file)
    12974 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12980     # check output
    12981     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
    12982     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
    12983     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
    12984     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
    12985     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
    12986     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
    12987     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
    12988     (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")
    12989     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
    12990     (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")
    12991     (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")
    12992     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
    12993     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
    12994     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
    12995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
    12996     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
    12997     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
    12998     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
    12999     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
    13000     # . epilogue
    13001     89/<- %esp 5/r32/ebp
    13002     5d/pop-to-ebp
    13003     c3/return
    13004
    13005 test-write-to-stream-with-non-stream-atom-base-type:
    13006     # . prologue
    13007     55/push-ebp
    13008     89/<- %ebp 4/r32/esp
    13009     # setup
    13010     (clear-stream _test-input-stream)
    13011     (clear-stream $_test-input-buffered-file->buffer)
    13012     (clear-stream _test-output-stream)
    13013     (clear-stream $_test-output-buffered-file->buffer)
    13014     (clear-stream _test-error-stream)
    13015     (clear-stream $_test-error-buffered-file->buffer)
    13016     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13017     68/push 0/imm32
    13018     68/push 0/imm32
    13019     89/<- %edx 4/r32/esp
    13020     (tailor-exit-descriptor %edx 0x10)
    13021     #
    13022     (write _test-input-stream "fn foo {\n")
    13023     (write _test-input-stream "  var a: int\n")
    13024     (write _test-input-stream "  write-to-stream a, 0\n")
    13025     (write _test-input-stream "}\n")
    13026     # convert
    13027     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13028     # registers except esp clobbered at this point
    13029     # restore ed
    13030     89/<- %edx 4/r32/esp
    13031     (flush _test-output-buffered-file)
    13032     (flush _test-error-buffered-file)
    13033 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13039     # check output
    13040     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
    13041     (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")
    13042     # check that stop(1) was called
    13043     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
    13044     # don't restore from ebp
    13045     81 0/subop/add %esp 8/imm32
    13046     # . epilogue
    13047     5d/pop-to-ebp
    13048     c3/return
    13049
    13050 test-write-to-stream-with-non-stream-compound-base-type:
    13051     # . prologue
    13052     55/push-ebp
    13053     89/<- %ebp 4/r32/esp
    13054     # setup
    13055     (clear-stream _test-input-stream)
    13056     (clear-stream $_test-input-buffered-file->buffer)
    13057     (clear-stream _test-output-stream)
    13058     (clear-stream $_test-output-buffered-file->buffer)
    13059     (clear-stream _test-error-stream)
    13060     (clear-stream $_test-error-buffered-file->buffer)
    13061     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13062     68/push 0/imm32
    13063     68/push 0/imm32
    13064     89/<- %edx 4/r32/esp
    13065     (tailor-exit-descriptor %edx 0x10)
    13066     #
    13067     (write _test-input-stream "fn foo {\n")
    13068     (write _test-input-stream "  var a: (handle int)\n")
    13069     (write _test-input-stream "  write-to-stream a, 0\n")
    13070     (write _test-input-stream "}\n")
    13071     # convert
    13072     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13073     # registers except esp clobbered at this point
    13074     # restore ed
    13075     89/<- %edx 4/r32/esp
    13076     (flush _test-output-buffered-file)
    13077     (flush _test-error-buffered-file)
    13078 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13084     # check output
    13085     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
    13086     (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")
    13087     # check that stop(1) was called
    13088     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
    13089     # don't restore from ebp
    13090     81 0/subop/add %esp 8/imm32
    13091     # . epilogue
    13092     5d/pop-to-ebp
    13093     c3/return
    13094
    13095 test-write-to-stream-with-non-stream-compound-base-type-2:
    13096     # . prologue
    13097     55/push-ebp
    13098     89/<- %ebp 4/r32/esp
    13099     # setup
    13100     (clear-stream _test-input-stream)
    13101     (clear-stream $_test-input-buffered-file->buffer)
    13102     (clear-stream _test-output-stream)
    13103     (clear-stream $_test-output-buffered-file->buffer)
    13104     (clear-stream _test-error-stream)
    13105     (clear-stream $_test-error-buffered-file->buffer)
    13106     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13107     68/push 0/imm32
    13108     68/push 0/imm32
    13109     89/<- %edx 4/r32/esp
    13110     (tailor-exit-descriptor %edx 0x10)
    13111     #
    13112     (write _test-input-stream "fn foo {\n")
    13113     (write _test-input-stream "  var a: (addr int)\n")
    13114     (write _test-input-stream "  write-to-stream a, 0\n")
    13115     (write _test-input-stream "}\n")
    13116     # convert
    13117     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13118     # registers except esp clobbered at this point
    13119     # restore ed
    13120     89/<- %edx 4/r32/esp
    13121     (flush _test-output-buffered-file)
    13122     (flush _test-error-buffered-file)
    13123 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13129     # check output
    13130     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
    13131     (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")
    13132     # check that stop(1) was called
    13133     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
    13134     # don't restore from ebp
    13135     81 0/subop/add %esp 8/imm32
    13136     # . epilogue
    13137     5d/pop-to-ebp
    13138     c3/return
    13139
    13140 test-write-to-stream-with-stream-atom-base-type:
    13141     # . prologue
    13142     55/push-ebp
    13143     89/<- %ebp 4/r32/esp
    13144     # setup
    13145     (clear-stream _test-input-stream)
    13146     (clear-stream $_test-input-buffered-file->buffer)
    13147     (clear-stream _test-output-stream)
    13148     (clear-stream $_test-output-buffered-file->buffer)
    13149     (clear-stream _test-error-stream)
    13150     (clear-stream $_test-error-buffered-file->buffer)
    13151     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13152     68/push 0/imm32
    13153     68/push 0/imm32
    13154     89/<- %edx 4/r32/esp
    13155     (tailor-exit-descriptor %edx 0x10)
    13156     #
    13157     (write _test-input-stream "fn foo {\n")
    13158     (write _test-input-stream "  var a: stream\n")
    13159     (write _test-input-stream "  write-to-stream a, 0\n")
    13160     (write _test-input-stream "}\n")
    13161     # convert
    13162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13163     # registers except esp clobbered at this point
    13164     # restore ed
    13165     89/<- %edx 4/r32/esp
    13166     (flush _test-output-buffered-file)
    13167     (flush _test-error-buffered-file)
    13168 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13174     # check output
    13175     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
    13176     (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")
    13177     # check that stop(1) was called
    13178     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
    13179     # don't restore from ebp
    13180     81 0/subop/add %esp 8/imm32
    13181     # . epilogue
    13182     5d/pop-to-ebp
    13183     c3/return
    13184
    13185 test-write-to-stream-with-wrong-index-type:
    13186     # . prologue
    13187     55/push-ebp
    13188     89/<- %ebp 4/r32/esp
    13189     # setup
    13190     (clear-stream _test-input-stream)
    13191     (clear-stream $_test-input-buffered-file->buffer)
    13192     (clear-stream _test-output-stream)
    13193     (clear-stream $_test-output-buffered-file->buffer)
    13194     (clear-stream _test-error-stream)
    13195     (clear-stream $_test-error-buffered-file->buffer)
    13196     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13197     68/push 0/imm32
    13198     68/push 0/imm32
    13199     89/<- %edx 4/r32/esp
    13200     (tailor-exit-descriptor %edx 0x10)
    13201     #
    13202     (write _test-input-stream "fn foo {\n")
    13203     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    13204     (write _test-input-stream "  var b: boolean\n")
    13205     (write _test-input-stream "  write-to-stream a, b\n")
    13206     (write _test-input-stream "}\n")
    13207     # convert
    13208     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13209     # registers except esp clobbered at this point
    13210     # restore ed
    13211     89/<- %edx 4/r32/esp
    13212     (flush _test-output-buffered-file)
    13213     (flush _test-error-buffered-file)
    13214 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13220     # check output
    13221     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
    13222     (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")
    13223     # check that stop(1) was called
    13224     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
    13225     # don't restore from ebp
    13226     81 0/subop/add %esp 8/imm32
    13227     # . epilogue
    13228     5d/pop-to-ebp
    13229     c3/return
    13230
    13231 test-write-to-stream-with-no-inouts:
    13232     # . prologue
    13233     55/push-ebp
    13234     89/<- %ebp 4/r32/esp
    13235     # setup
    13236     (clear-stream _test-input-stream)
    13237     (clear-stream $_test-input-buffered-file->buffer)
    13238     (clear-stream _test-output-stream)
    13239     (clear-stream $_test-output-buffered-file->buffer)
    13240     (clear-stream _test-error-stream)
    13241     (clear-stream $_test-error-buffered-file->buffer)
    13242     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13243     68/push 0/imm32
    13244     68/push 0/imm32
    13245     89/<- %edx 4/r32/esp
    13246     (tailor-exit-descriptor %edx 0x10)
    13247     #
    13248     (write _test-input-stream "fn foo {\n")
    13249     (write _test-input-stream "  write-to-stream\n")
    13250     (write _test-input-stream "}\n")
    13251     # convert
    13252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13253     # registers except esp clobbered at this point
    13254     # restore ed
    13255     89/<- %edx 4/r32/esp
    13256     (flush _test-output-buffered-file)
    13257     (flush _test-error-buffered-file)
    13258 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13264     # check output
    13265     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
    13266     (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")
    13267     # check that stop(1) was called
    13268     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
    13269     # don't restore from ebp
    13270     81 0/subop/add %esp 8/imm32
    13271     # . epilogue
    13272     5d/pop-to-ebp
    13273     c3/return
    13274
    13275 test-write-to-stream-with-too-few-inouts:
    13276     # . prologue
    13277     55/push-ebp
    13278     89/<- %ebp 4/r32/esp
    13279     # setup
    13280     (clear-stream _test-input-stream)
    13281     (clear-stream $_test-input-buffered-file->buffer)
    13282     (clear-stream _test-output-stream)
    13283     (clear-stream $_test-output-buffered-file->buffer)
    13284     (clear-stream _test-error-stream)
    13285     (clear-stream $_test-error-buffered-file->buffer)
    13286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13287     68/push 0/imm32
    13288     68/push 0/imm32
    13289     89/<- %edx 4/r32/esp
    13290     (tailor-exit-descriptor %edx 0x10)
    13291     #
    13292     (write _test-input-stream "fn foo {\n")
    13293     (write _test-input-stream "  var a: (addr stream int)\n")
    13294     (write _test-input-stream "  write-to-stream a\n")
    13295     (write _test-input-stream "}\n")
    13296     # convert
    13297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13298     # registers except esp clobbered at this point
    13299     # restore ed
    13300     89/<- %edx 4/r32/esp
    13301     (flush _test-output-buffered-file)
    13302     (flush _test-error-buffered-file)
    13303 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13309     # check output
    13310     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
    13311     (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")
    13312     # check that stop(1) was called
    13313     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
    13314     # don't restore from ebp
    13315     81 0/subop/add %esp 8/imm32
    13316     # . epilogue
    13317     5d/pop-to-ebp
    13318     c3/return
    13319
    13320 test-write-to-stream-with-too-many-inouts:
    13321     # . prologue
    13322     55/push-ebp
    13323     89/<- %ebp 4/r32/esp
    13324     # setup
    13325     (clear-stream _test-input-stream)
    13326     (clear-stream $_test-input-buffered-file->buffer)
    13327     (clear-stream _test-output-stream)
    13328     (clear-stream $_test-output-buffered-file->buffer)
    13329     (clear-stream _test-error-stream)
    13330     (clear-stream $_test-error-buffered-file->buffer)
    13331     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13332     68/push 0/imm32
    13333     68/push 0/imm32
    13334     89/<- %edx 4/r32/esp
    13335     (tailor-exit-descriptor %edx 0x10)
    13336     #
    13337     (write _test-input-stream "fn foo {\n")
    13338     (write _test-input-stream "  var a: (addr stream int)\n")
    13339     (write _test-input-stream "  var b: (addr int)\n")
    13340     (write _test-input-stream "  write-to-stream a, b, 0\n")
    13341     (write _test-input-stream "}\n")
    13342     # convert
    13343     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13344     # registers except esp clobbered at this point
    13345     # restore ed
    13346     89/<- %edx 4/r32/esp
    13347     (flush _test-output-buffered-file)
    13348     (flush _test-error-buffered-file)
    13349 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13355     # check output
    13356     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
    13357     (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")
    13358     # check that stop(1) was called
    13359     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
    13360     # don't restore from ebp
    13361     81 0/subop/add %esp 8/imm32
    13362     # . epilogue
    13363     5d/pop-to-ebp
    13364     c3/return
    13365
    13366 test-write-to-stream-with-output:
    13367     # . prologue
    13368     55/push-ebp
    13369     89/<- %ebp 4/r32/esp
    13370     # setup
    13371     (clear-stream _test-input-stream)
    13372     (clear-stream $_test-input-buffered-file->buffer)
    13373     (clear-stream _test-output-stream)
    13374     (clear-stream $_test-output-buffered-file->buffer)
    13375     (clear-stream _test-error-stream)
    13376     (clear-stream $_test-error-buffered-file->buffer)
    13377     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13378     68/push 0/imm32
    13379     68/push 0/imm32
    13380     89/<- %edx 4/r32/esp
    13381     (tailor-exit-descriptor %edx 0x10)
    13382     #
    13383     (write _test-input-stream "fn foo {\n")
    13384     (write _test-input-stream "  var a: (addr stream int)\n")
    13385     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    13386     (write _test-input-stream "  b <- write-to-stream a, b\n")
    13387     (write _test-input-stream "}\n")
    13388     # convert
    13389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13390     # registers except esp clobbered at this point
    13391     # restore ed
    13392     89/<- %edx 4/r32/esp
    13393     (flush _test-output-buffered-file)
    13394     (flush _test-error-buffered-file)
    13395 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13401     # check output
    13402     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
    13403     (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")
    13404     # check that stop(1) was called
    13405     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
    13406     # don't restore from ebp
    13407     81 0/subop/add %esp 8/imm32
    13408     # . epilogue
    13409     5d/pop-to-ebp
    13410     c3/return
    13411
    13412 test-length-with-non-array-atom-base-type:
    13413     # . prologue
    13414     55/push-ebp
    13415     89/<- %ebp 4/r32/esp
    13416     # setup
    13417     (clear-stream _test-input-stream)
    13418     (clear-stream $_test-input-buffered-file->buffer)
    13419     (clear-stream _test-output-stream)
    13420     (clear-stream $_test-output-buffered-file->buffer)
    13421     (clear-stream _test-error-stream)
    13422     (clear-stream $_test-error-buffered-file->buffer)
    13423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13424     68/push 0/imm32
    13425     68/push 0/imm32
    13426     89/<- %edx 4/r32/esp
    13427     (tailor-exit-descriptor %edx 0x10)
    13428     #
    13429     (write _test-input-stream "fn foo {\n")
    13430     (write _test-input-stream "  var a: int\n")
    13431     (write _test-input-stream "  var c/ecx: int <- length a\n")
    13432     (write _test-input-stream "}\n")
    13433     # convert
    13434     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13435     # registers except esp clobbered at this point
    13436     # restore ed
    13437     89/<- %edx 4/r32/esp
    13438     (flush _test-output-buffered-file)
    13439     (flush _test-error-buffered-file)
    13440 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13446     # check output
    13447     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
    13448     (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")
    13449     # check that stop(1) was called
    13450     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
    13451     # don't restore from ebp
    13452     81 0/subop/add %esp 8/imm32
    13453     # . epilogue
    13454     5d/pop-to-ebp
    13455     c3/return
    13456
    13457 test-length-with-non-array-compound-base-type:
    13458     # . prologue
    13459     55/push-ebp
    13460     89/<- %ebp 4/r32/esp
    13461     # setup
    13462     (clear-stream _test-input-stream)
    13463     (clear-stream $_test-input-buffered-file->buffer)
    13464     (clear-stream _test-output-stream)
    13465     (clear-stream $_test-output-buffered-file->buffer)
    13466     (clear-stream _test-error-stream)
    13467     (clear-stream $_test-error-buffered-file->buffer)
    13468     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13469     68/push 0/imm32
    13470     68/push 0/imm32
    13471     89/<- %edx 4/r32/esp
    13472     (tailor-exit-descriptor %edx 0x10)
    13473     #
    13474     (write _test-input-stream "fn foo {\n")
    13475     (write _test-input-stream "  var a: (handle int)\n")
    13476     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13477     (write _test-input-stream "}\n")
    13478     # convert
    13479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13480     # registers except esp clobbered at this point
    13481     # restore ed
    13482     89/<- %edx 4/r32/esp
    13483     (flush _test-output-buffered-file)
    13484     (flush _test-error-buffered-file)
    13485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13491     # check output
    13492     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
    13493     (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")
    13494     # check that stop(1) was called
    13495     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
    13496     # don't restore from ebp
    13497     81 0/subop/add %esp 8/imm32
    13498     # . epilogue
    13499     5d/pop-to-ebp
    13500     c3/return
    13501
    13502 test-length-with-non-array-compound-base-type-2:
    13503     # . prologue
    13504     55/push-ebp
    13505     89/<- %ebp 4/r32/esp
    13506     # setup
    13507     (clear-stream _test-input-stream)
    13508     (clear-stream $_test-input-buffered-file->buffer)
    13509     (clear-stream _test-output-stream)
    13510     (clear-stream $_test-output-buffered-file->buffer)
    13511     (clear-stream _test-error-stream)
    13512     (clear-stream $_test-error-buffered-file->buffer)
    13513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13514     68/push 0/imm32
    13515     68/push 0/imm32
    13516     89/<- %edx 4/r32/esp
    13517     (tailor-exit-descriptor %edx 0x10)
    13518     #
    13519     (write _test-input-stream "fn foo {\n")
    13520     (write _test-input-stream "  var a: (addr int)\n")
    13521     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13522     (write _test-input-stream "}\n")
    13523     # convert
    13524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13525     # registers except esp clobbered at this point
    13526     # restore ed
    13527     89/<- %edx 4/r32/esp
    13528     (flush _test-output-buffered-file)
    13529     (flush _test-error-buffered-file)
    13530 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13536     # check output
    13537     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
    13538     (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")
    13539     # check that stop(1) was called
    13540     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
    13541     # don't restore from ebp
    13542     81 0/subop/add %esp 8/imm32
    13543     # . epilogue
    13544     5d/pop-to-ebp
    13545     c3/return
    13546
    13547 test-length-with-array-atom-base-type:
    13548     # . prologue
    13549     55/push-ebp
    13550     89/<- %ebp 4/r32/esp
    13551     # setup
    13552     (clear-stream _test-input-stream)
    13553     (clear-stream $_test-input-buffered-file->buffer)
    13554     (clear-stream _test-output-stream)
    13555     (clear-stream $_test-output-buffered-file->buffer)
    13556     (clear-stream _test-error-stream)
    13557     (clear-stream $_test-error-buffered-file->buffer)
    13558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13559     68/push 0/imm32
    13560     68/push 0/imm32
    13561     89/<- %edx 4/r32/esp
    13562     (tailor-exit-descriptor %edx 0x10)
    13563     #
    13564     (write _test-input-stream "fn foo {\n")
    13565     (write _test-input-stream "  var a: array\n")
    13566     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13567     (write _test-input-stream "}\n")
    13568     # convert
    13569     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13570     # registers except esp clobbered at this point
    13571     # restore ed
    13572     89/<- %edx 4/r32/esp
    13573     (flush _test-output-buffered-file)
    13574     (flush _test-error-buffered-file)
    13575 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13581     # check output
    13582     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
    13583     (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")
    13584     # check that stop(1) was called
    13585     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
    13586     # don't restore from ebp
    13587     81 0/subop/add %esp 8/imm32
    13588     # . epilogue
    13589     5d/pop-to-ebp
    13590     c3/return
    13591
    13592 test-length-with-addr-base-on-stack:
    13593     # . prologue
    13594     55/push-ebp
    13595     89/<- %ebp 4/r32/esp
    13596     # setup
    13597     (clear-stream _test-input-stream)
    13598     (clear-stream $_test-input-buffered-file->buffer)
    13599     (clear-stream _test-output-stream)
    13600     (clear-stream $_test-output-buffered-file->buffer)
    13601     (clear-stream _test-error-stream)
    13602     (clear-stream $_test-error-buffered-file->buffer)
    13603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13604     68/push 0/imm32
    13605     68/push 0/imm32
    13606     89/<- %edx 4/r32/esp
    13607     (tailor-exit-descriptor %edx 0x10)
    13608     #
    13609     (write _test-input-stream "fn foo {\n")
    13610     (write _test-input-stream "  var a: (addr array int)\n")
    13611     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13612     (write _test-input-stream "}\n")
    13613     # convert
    13614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13615     # registers except esp clobbered at this point
    13616     # restore ed
    13617     89/<- %edx 4/r32/esp
    13618     (flush _test-output-buffered-file)
    13619     (flush _test-error-buffered-file)
    13620 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13626     # check output
    13627     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
    13628     (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")
    13629     # check that stop(1) was called
    13630     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
    13631     # don't restore from ebp
    13632     81 0/subop/add %esp 8/imm32
    13633     # . epilogue
    13634     5d/pop-to-ebp
    13635     c3/return
    13636
    13637 test-length-with-wrong-output-type:
    13638     # . prologue
    13639     55/push-ebp
    13640     89/<- %ebp 4/r32/esp
    13641     # setup
    13642     (clear-stream _test-input-stream)
    13643     (clear-stream $_test-input-buffered-file->buffer)
    13644     (clear-stream _test-output-stream)
    13645     (clear-stream $_test-output-buffered-file->buffer)
    13646     (clear-stream _test-error-stream)
    13647     (clear-stream $_test-error-buffered-file->buffer)
    13648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13649     68/push 0/imm32
    13650     68/push 0/imm32
    13651     89/<- %edx 4/r32/esp
    13652     (tailor-exit-descriptor %edx 0x10)
    13653     #
    13654     (write _test-input-stream "fn foo {\n")
    13655     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    13656     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
    13657     (write _test-input-stream "}\n")
    13658     # convert
    13659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13660     # registers except esp clobbered at this point
    13661     # restore ed
    13662     89/<- %edx 4/r32/esp
    13663     (flush _test-output-buffered-file)
    13664     (flush _test-error-buffered-file)
    13665 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13671     # check output
    13672     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
    13673     (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")
    13674     # check that stop(1) was called
    13675     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
    13676     # don't restore from ebp
    13677     81 0/subop/add %esp 8/imm32
    13678     # . epilogue
    13679     5d/pop-to-ebp
    13680     c3/return
    13681
    13682 test-length-with-wrong-output-compound-type:
    13683     # . prologue
    13684     55/push-ebp
    13685     89/<- %ebp 4/r32/esp
    13686     # setup
    13687     (clear-stream _test-input-stream)
    13688     (clear-stream $_test-input-buffered-file->buffer)
    13689     (clear-stream _test-output-stream)
    13690     (clear-stream $_test-output-buffered-file->buffer)
    13691     (clear-stream _test-error-stream)
    13692     (clear-stream $_test-error-buffered-file->buffer)
    13693     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13694     68/push 0/imm32
    13695     68/push 0/imm32
    13696     89/<- %edx 4/r32/esp
    13697     (tailor-exit-descriptor %edx 0x10)
    13698     #
    13699     (write _test-input-stream "fn foo {\n")
    13700     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    13701     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
    13702     (write _test-input-stream "}\n")
    13703     # convert
    13704     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13705     # registers except esp clobbered at this point
    13706     # restore ed
    13707     89/<- %edx 4/r32/esp
    13708     (flush _test-output-buffered-file)
    13709     (flush _test-error-buffered-file)
    13710 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13716     # check output
    13717     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
    13718     (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")
    13719     # check that stop(1) was called
    13720     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
    13721     # don't restore from ebp
    13722     81 0/subop/add %esp 8/imm32
    13723     # . epilogue
    13724     5d/pop-to-ebp
    13725     c3/return
    13726
    13727 test-length-with-no-inouts:
    13728     # . prologue
    13729     55/push-ebp
    13730     89/<- %ebp 4/r32/esp
    13731     # setup
    13732     (clear-stream _test-input-stream)
    13733     (clear-stream $_test-input-buffered-file->buffer)
    13734     (clear-stream _test-output-stream)
    13735     (clear-stream $_test-output-buffered-file->buffer)
    13736     (clear-stream _test-error-stream)
    13737     (clear-stream $_test-error-buffered-file->buffer)
    13738     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13739     68/push 0/imm32
    13740     68/push 0/imm32
    13741     89/<- %edx 4/r32/esp
    13742     (tailor-exit-descriptor %edx 0x10)
    13743     #
    13744     (write _test-input-stream "fn foo {\n")
    13745     (write _test-input-stream "  var c/ecx: int <- length\n")
    13746     (write _test-input-stream "}\n")
    13747     # convert
    13748     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13749     # registers except esp clobbered at this point
    13750     # restore ed
    13751     89/<- %edx 4/r32/esp
    13752     (flush _test-output-buffered-file)
    13753     (flush _test-error-buffered-file)
    13754 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13760     # check output
    13761     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
    13762     (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")
    13763     # check that stop(1) was called
    13764     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
    13765     # don't restore from ebp
    13766     81 0/subop/add %esp 8/imm32
    13767     # . epilogue
    13768     5d/pop-to-ebp
    13769     c3/return
    13770
    13771 test-length-with-too-many-inouts:
    13772     # . prologue
    13773     55/push-ebp
    13774     89/<- %ebp 4/r32/esp
    13775     # setup
    13776     (clear-stream _test-input-stream)
    13777     (clear-stream $_test-input-buffered-file->buffer)
    13778     (clear-stream _test-output-stream)
    13779     (clear-stream $_test-output-buffered-file->buffer)
    13780     (clear-stream _test-error-stream)
    13781     (clear-stream $_test-error-buffered-file->buffer)
    13782     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13783     68/push 0/imm32
    13784     68/push 0/imm32
    13785     89/<- %edx 4/r32/esp
    13786     (tailor-exit-descriptor %edx 0x10)
    13787     #
    13788     (write _test-input-stream "fn foo {\n")
    13789     (write _test-input-stream "  var a: (array int 3)\n")
    13790     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
    13791     (write _test-input-stream "}\n")
    13792     # convert
    13793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13794     # registers except esp clobbered at this point
    13795     # restore ed
    13796     89/<- %edx 4/r32/esp
    13797     (flush _test-output-buffered-file)
    13798     (flush _test-error-buffered-file)
    13799 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13805     # check output
    13806     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
    13807     (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")
    13808     # check that stop(1) was called
    13809     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
    13810     # don't restore from ebp
    13811     81 0/subop/add %esp 8/imm32
    13812     # . epilogue
    13813     5d/pop-to-ebp
    13814     c3/return
    13815
    13816 test-length-with-no-output:
    13817     # . prologue
    13818     55/push-ebp
    13819     89/<- %ebp 4/r32/esp
    13820     # setup
    13821     (clear-stream _test-input-stream)
    13822     (clear-stream $_test-input-buffered-file->buffer)
    13823     (clear-stream _test-output-stream)
    13824     (clear-stream $_test-output-buffered-file->buffer)
    13825     (clear-stream _test-error-stream)
    13826     (clear-stream $_test-error-buffered-file->buffer)
    13827     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13828     68/push 0/imm32
    13829     68/push 0/imm32
    13830     89/<- %edx 4/r32/esp
    13831     (tailor-exit-descriptor %edx 0x10)
    13832     #
    13833     (write _test-input-stream "fn foo {\n")
    13834     (write _test-input-stream "  var a: (array int 3)\n")
    13835     (write _test-input-stream "  length a\n")
    13836     (write _test-input-stream "}\n")
    13837     # convert
    13838     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13839     # registers except esp clobbered at this point
    13840     # restore ed
    13841     89/<- %edx 4/r32/esp
    13842     (flush _test-output-buffered-file)
    13843     (flush _test-error-buffered-file)
    13844 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13850     # check output
    13851     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
    13852     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
    13853     # check that stop(1) was called
    13854     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
    13855     # don't restore from ebp
    13856     81 0/subop/add %esp 8/imm32
    13857     # . epilogue
    13858     5d/pop-to-ebp
    13859     c3/return
    13860
    13861 test-length-with-too-many-outputs:
    13862     # . prologue
    13863     55/push-ebp
    13864     89/<- %ebp 4/r32/esp
    13865     # setup
    13866     (clear-stream _test-input-stream)
    13867     (clear-stream $_test-input-buffered-file->buffer)
    13868     (clear-stream _test-output-stream)
    13869     (clear-stream $_test-output-buffered-file->buffer)
    13870     (clear-stream _test-error-stream)
    13871     (clear-stream $_test-error-buffered-file->buffer)
    13872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13873     68/push 0/imm32
    13874     68/push 0/imm32
    13875     89/<- %edx 4/r32/esp
    13876     (tailor-exit-descriptor %edx 0x10)
    13877     #
    13878     (write _test-input-stream "fn foo {\n")
    13879     (write _test-input-stream "  var a: (array int 3)\n")
    13880     (write _test-input-stream "  var b/eax: int <- copy 0\n")
    13881     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
    13882     (write _test-input-stream "  b, c <- 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-too-many-outputs: output should be empty")
    13899     (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")
    13900     # check that stop(1) was called
    13901     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: 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-convert-function-with-return-register-and-local:
    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     #
    13918     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13919     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13920     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13921     (write _test-input-stream "  return y\n")
    13922     (write _test-input-stream "}\n")
    13923     # convert
    13924     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13925     (flush _test-output-buffered-file)
    13926 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    13932     # check output
    13933     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
    13934     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
    13935     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
    13936     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
    13937     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
    13938     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
    13939     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
    13940     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
    13941     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
    13942     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
    13943     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
    13944     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
    13945     (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")
    13946     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
    13947     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
    13948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
    13949     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
    13950     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
    13951     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
    13952     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
    13953     # . epilogue
    13954     89/<- %esp 5/r32/ebp
    13955     5d/pop-to-ebp
    13956     c3/return
    13957
    13958 test-convert-function-with-return-register-and-local-2:
    13959     # . prologue
    13960     55/push-ebp
    13961     89/<- %ebp 4/r32/esp
    13962     # setup
    13963     (clear-stream _test-input-stream)
    13964     (clear-stream $_test-input-buffered-file->buffer)
    13965     (clear-stream _test-output-stream)
    13966     (clear-stream $_test-output-buffered-file->buffer)
    13967     #
    13968     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13969     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13970     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13971     (write _test-input-stream "  return z\n")
    13972     (write _test-input-stream "}\n")
    13973     # convert
    13974     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13975     (flush _test-output-buffered-file)
    13976 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    13982     # check output
    13983     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
    13984     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
    13985     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
    13986     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
    13987     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
    13988     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
    13989     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
    13990     (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")
    13991     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
    13992     (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")
    13993     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
    13994     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
    13995     (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")
    13996     (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")
    13997     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
    13998     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
    13999     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
    14000     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
    14001     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
    14002     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
    14003     # . epilogue
    14004     89/<- %esp 5/r32/ebp
    14005     5d/pop-to-ebp
    14006     c3/return
    14007
    14008 test-convert-function-with-return-float-register-and-local:
    14009     # . prologue
    14010     55/push-ebp
    14011     89/<- %ebp 4/r32/esp
    14012     # setup
    14013     (clear-stream _test-input-stream)
    14014     (clear-stream $_test-input-buffered-file->buffer)
    14015     (clear-stream _test-output-stream)
    14016     (clear-stream $_test-output-buffered-file->buffer)
    14017     #
    14018     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
    14019     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    14020     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
    14021     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
    14022     (write _test-input-stream "  return g\n")
    14023     (write _test-input-stream "}\n")
    14024     # convert
    14025     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14026     (flush _test-output-buffered-file)
    14027 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14033     # check output
    14034     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
    14035     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
    14036     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
    14037     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
    14038     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
    14039     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
    14040     (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
    14041     (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")
    14042     (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
    14043     (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")
    14044     (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")
    14045     (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
    14046     (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")
    14047     (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")
    14048     (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
    14049     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
    14050     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
    14051     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
    14052     (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
    14053     (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")
    14054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
    14055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
    14056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
    14057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
    14058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
    14059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
    14060     # . epilogue
    14061     89/<- %esp 5/r32/ebp
    14062     5d/pop-to-ebp
    14063     c3/return
    14064
    14065 test-convert-function-with-return-and-local-vars:
    14066     # . prologue
    14067     55/push-ebp
    14068     89/<- %ebp 4/r32/esp
    14069     # setup
    14070     (clear-stream _test-input-stream)
    14071     (clear-stream $_test-input-buffered-file->buffer)
    14072     (clear-stream _test-output-stream)
    14073     (clear-stream $_test-output-buffered-file->buffer)
    14074     #
    14075     (write _test-input-stream "fn foo -> _/eax: int {\n")
    14076     (write _test-input-stream "  {\n")
    14077     (write _test-input-stream "    var x: int\n")
    14078     (write _test-input-stream "    {\n")
    14079     (write _test-input-stream "      var y: int\n")
    14080     (write _test-input-stream "      return y\n")
    14081     (write _test-input-stream "      increment x\n")
    14082     (write _test-input-stream "    }\n")
    14083     (write _test-input-stream "  }\n")
    14084     (write _test-input-stream "  return 0\n")
    14085     (write _test-input-stream "}\n")
    14086     # convert
    14087     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14088     (flush _test-output-buffered-file)
    14089 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14095     # check output
    14096     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
    14097     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
    14098     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
    14099     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
    14100     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
    14101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
    14102     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
    14103     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
    14104     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
    14105     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
    14106     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
    14107     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
    14108     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
    14109     (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")
    14110     (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")
    14111     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
    14112     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
    14113     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
    14114     (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")
    14115     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
    14116     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
    14117     (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")
    14118     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
    14119     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
    14120     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
    14121     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
    14122     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
    14123     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
    14124     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
    14125     # . epilogue
    14126     89/<- %esp 5/r32/ebp
    14127     5d/pop-to-ebp
    14128     c3/return
    14129
    14130 test-copy-object-with-no-inout:
    14131     # . prologue
    14132     55/push-ebp
    14133     89/<- %ebp 4/r32/esp
    14134     # setup
    14135     (clear-stream _test-input-stream)
    14136     (clear-stream $_test-input-buffered-file->buffer)
    14137     (clear-stream _test-output-stream)
    14138     (clear-stream $_test-output-buffered-file->buffer)
    14139     (clear-stream _test-error-stream)
    14140     (clear-stream $_test-error-buffered-file->buffer)
    14141     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14142     68/push 0/imm32
    14143     68/push 0/imm32
    14144     89/<- %edx 4/r32/esp
    14145     (tailor-exit-descriptor %edx 0x10)
    14146     #
    14147     (write _test-input-stream "fn foo {\n")
    14148     (write _test-input-stream "  copy-object\n")
    14149     (write _test-input-stream "}\n")
    14150     # convert
    14151     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14152     # registers except esp clobbered at this point
    14153     # restore ed
    14154     89/<- %edx 4/r32/esp
    14155     (flush _test-output-buffered-file)
    14156     (flush _test-error-buffered-file)
    14157 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14163     # check output
    14164     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
    14165     (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")
    14166     # check that stop(1) was called
    14167     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
    14168     # don't restore from ebp
    14169     81 0/subop/add %esp 8/imm32
    14170     # . epilogue
    14171     5d/pop-to-ebp
    14172     c3/return
    14173
    14174 test-copy-object-with-no-source:
    14175     # . prologue
    14176     55/push-ebp
    14177     89/<- %ebp 4/r32/esp
    14178     # setup
    14179     (clear-stream _test-input-stream)
    14180     (clear-stream $_test-input-buffered-file->buffer)
    14181     (clear-stream _test-output-stream)
    14182     (clear-stream $_test-output-buffered-file->buffer)
    14183     (clear-stream _test-error-stream)
    14184     (clear-stream $_test-error-buffered-file->buffer)
    14185     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14186     68/push 0/imm32
    14187     68/push 0/imm32
    14188     89/<- %edx 4/r32/esp
    14189     (tailor-exit-descriptor %edx 0x10)
    14190     #
    14191     (write _test-input-stream "fn foo {\n")
    14192     (write _test-input-stream "  var x: (addr int)\n")
    14193     (write _test-input-stream "  copy-object x\n")
    14194     (write _test-input-stream "}\n")
    14195     # convert
    14196     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14197     # registers except esp clobbered at this point
    14198     # restore ed
    14199     89/<- %edx 4/r32/esp
    14200     (flush _test-output-buffered-file)
    14201     (flush _test-error-buffered-file)
    14202 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14208     # check output
    14209     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
    14210     (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")
    14211     # check that stop(1) was called
    14212     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
    14213     # don't restore from ebp
    14214     81 0/subop/add %esp 8/imm32
    14215     # . epilogue
    14216     5d/pop-to-ebp
    14217     c3/return
    14218
    14219 test-copy-object-with-too-many-inouts:
    14220     # . prologue
    14221     55/push-ebp
    14222     89/<- %ebp 4/r32/esp
    14223     # setup
    14224     (clear-stream _test-input-stream)
    14225     (clear-stream $_test-input-buffered-file->buffer)
    14226     (clear-stream _test-output-stream)
    14227     (clear-stream $_test-output-buffered-file->buffer)
    14228     (clear-stream _test-error-stream)
    14229     (clear-stream $_test-error-buffered-file->buffer)
    14230     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14231     68/push 0/imm32
    14232     68/push 0/imm32
    14233     89/<- %edx 4/r32/esp
    14234     (tailor-exit-descriptor %edx 0x10)
    14235     #
    14236     (write _test-input-stream "fn foo {\n")
    14237     (write _test-input-stream "  var x: (addr boolean)\n")
    14238     (write _test-input-stream "  copy-object x, x, x\n")
    14239     (write _test-input-stream "}\n")
    14240     # convert
    14241     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14242     # registers except esp clobbered at this point
    14243     # restore ed
    14244     89/<- %edx 4/r32/esp
    14245     (flush _test-output-buffered-file)
    14246     (flush _test-error-buffered-file)
    14247 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14253     # check output
    14254     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
    14255     (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")
    14256     # check that stop(1) was called
    14257     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
    14258     # don't restore from ebp
    14259     81 0/subop/add %esp 8/imm32
    14260     # . epilogue
    14261     5d/pop-to-ebp
    14262     c3/return
    14263
    14264 test-copy-object-with-output:
    14265     # . prologue
    14266     55/push-ebp
    14267     89/<- %ebp 4/r32/esp
    14268     # setup
    14269     (clear-stream _test-input-stream)
    14270     (clear-stream $_test-input-buffered-file->buffer)
    14271     (clear-stream _test-output-stream)
    14272     (clear-stream $_test-output-buffered-file->buffer)
    14273     (clear-stream _test-error-stream)
    14274     (clear-stream $_test-error-buffered-file->buffer)
    14275     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14276     68/push 0/imm32
    14277     68/push 0/imm32
    14278     89/<- %edx 4/r32/esp
    14279     (tailor-exit-descriptor %edx 0x10)
    14280     #
    14281     (write _test-input-stream "fn foo {\n")
    14282     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
    14283     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
    14284     (write _test-input-stream "  x <- copy-object x, y\n")
    14285     (write _test-input-stream "}\n")
    14286     # convert
    14287     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14288     # registers except esp clobbered at this point
    14289     # restore ed
    14290     89/<- %edx 4/r32/esp
    14291     (flush _test-output-buffered-file)
    14292     (flush _test-error-buffered-file)
    14293 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14299     # check output
    14300     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
    14301     (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")
    14302     # check that stop(1) was called
    14303     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
    14304     # don't restore from ebp
    14305     81 0/subop/add %esp 8/imm32
    14306     # . epilogue
    14307     5d/pop-to-ebp
    14308     c3/return
    14309
    14310 test-copy-object-deref-address:
    14311     # . prologue
    14312     55/push-ebp
    14313     89/<- %ebp 4/r32/esp
    14314     # setup
    14315     (clear-stream _test-input-stream)
    14316     (clear-stream $_test-input-buffered-file->buffer)
    14317     (clear-stream _test-output-stream)
    14318     (clear-stream $_test-output-buffered-file->buffer)
    14319     #
    14320     (write _test-input-stream "fn foo {\n")
    14321     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    14322     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
    14323     (write _test-input-stream "  copy-object *y, x\n")
    14324     (write _test-input-stream "}\n")
    14325     # convert
    14326     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14327     (flush _test-output-buffered-file)
    14328     # no errors
    14329     # . epilogue
    14330     5d/pop-to-ebp
    14331     c3/return
    14332
    14333 test-copy-object-non-addr:
    14334     # . prologue
    14335     55/push-ebp
    14336     89/<- %ebp 4/r32/esp
    14337     # setup
    14338     (clear-stream _test-input-stream)
    14339     (clear-stream $_test-input-buffered-file->buffer)
    14340     (clear-stream _test-output-stream)
    14341     (clear-stream $_test-output-buffered-file->buffer)
    14342     (clear-stream _test-error-stream)
    14343     (clear-stream $_test-error-buffered-file->buffer)
    14344     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14345     68/push 0/imm32
    14346     68/push 0/imm32
    14347     89/<- %edx 4/r32/esp
    14348     (tailor-exit-descriptor %edx 0x10)
    14349     #
    14350     (write _test-input-stream "fn foo {\n")
    14351     (write _test-input-stream "  var x: int\n")
    14352     (write _test-input-stream "  var y: int\n")
    14353     (write _test-input-stream "  copy-object y, x\n")
    14354     (write _test-input-stream "}\n")
    14355     # convert
    14356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14357     # registers except esp clobbered at this point
    14358     # restore ed
    14359     89/<- %edx 4/r32/esp
    14360     (flush _test-output-buffered-file)
    14361     (flush _test-error-buffered-file)
    14362 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14368     # check output
    14369     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
    14370     (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")
    14371     # check that stop(1) was called
    14372     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
    14373     # don't restore from ebp
    14374     81 0/subop/add %esp 8/imm32
    14375     # . epilogue
    14376     5d/pop-to-ebp
    14377     c3/return
    14378
    14379 test-copy-object-non-equal:
    14380     # . prologue
    14381     55/push-ebp
    14382     89/<- %ebp 4/r32/esp
    14383     # setup
    14384     (clear-stream _test-input-stream)
    14385     (clear-stream $_test-input-buffered-file->buffer)
    14386     (clear-stream _test-output-stream)
    14387     (clear-stream $_test-output-buffered-file->buffer)
    14388     (clear-stream _test-error-stream)
    14389     (clear-stream $_test-error-buffered-file->buffer)
    14390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14391     68/push 0/imm32
    14392     68/push 0/imm32
    14393     89/<- %edx 4/r32/esp
    14394     (tailor-exit-descriptor %edx 0x10)
    14395     #
    14396     (write _test-input-stream "fn foo {\n")
    14397     (write _test-input-stream "  var x: (addr int)\n")
    14398     (write _test-input-stream "  var y: (addr boolean)\n")
    14399     (write _test-input-stream "  copy-object y, x\n")
    14400     (write _test-input-stream "}\n")
    14401     # convert
    14402     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14403     # registers except esp clobbered at this point
    14404     # restore ed
    14405     89/<- %edx 4/r32/esp
    14406     (flush _test-output-buffered-file)
    14407     (flush _test-error-buffered-file)
    14408 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14414     # check output
    14415     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
    14416     (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")
    14417     # check that stop(1) was called
    14418     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
    14419     # don't restore from ebp
    14420     81 0/subop/add %esp 8/imm32
    14421     # . epilogue
    14422     5d/pop-to-ebp
    14423     c3/return
    14424
    14425 test-allocate-with-no-inout:
    14426     # . prologue
    14427     55/push-ebp
    14428     89/<- %ebp 4/r32/esp
    14429     # setup
    14430     (clear-stream _test-input-stream)
    14431     (clear-stream $_test-input-buffered-file->buffer)
    14432     (clear-stream _test-output-stream)
    14433     (clear-stream $_test-output-buffered-file->buffer)
    14434     (clear-stream _test-error-stream)
    14435     (clear-stream $_test-error-buffered-file->buffer)
    14436     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14437     68/push 0/imm32
    14438     68/push 0/imm32
    14439     89/<- %edx 4/r32/esp
    14440     (tailor-exit-descriptor %edx 0x10)
    14441     #
    14442     (write _test-input-stream "fn foo {\n")
    14443     (write _test-input-stream "  allocate\n")
    14444     (write _test-input-stream "}\n")
    14445     # convert
    14446     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14447     # registers except esp clobbered at this point
    14448     # restore ed
    14449     89/<- %edx 4/r32/esp
    14450     (flush _test-output-buffered-file)
    14451     (flush _test-error-buffered-file)
    14452 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14458     # check output
    14459     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
    14460     (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")
    14461     # check that stop(1) was called
    14462     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
    14463     # don't restore from ebp
    14464     81 0/subop/add %esp 8/imm32
    14465     # . epilogue
    14466     5d/pop-to-ebp
    14467     c3/return
    14468
    14469 test-allocate-with-too-many-inouts:
    14470     # . prologue
    14471     55/push-ebp
    14472     89/<- %ebp 4/r32/esp
    14473     # setup
    14474     (clear-stream _test-input-stream)
    14475     (clear-stream $_test-input-buffered-file->buffer)
    14476     (clear-stream _test-output-stream)
    14477     (clear-stream $_test-output-buffered-file->buffer)
    14478     (clear-stream _test-error-stream)
    14479     (clear-stream $_test-error-buffered-file->buffer)
    14480     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14481     68/push 0/imm32
    14482     68/push 0/imm32
    14483     89/<- %edx 4/r32/esp
    14484     (tailor-exit-descriptor %edx 0x10)
    14485     #
    14486     (write _test-input-stream "fn foo {\n")
    14487     (write _test-input-stream "  var x: (addr handle int)\n")
    14488     (write _test-input-stream "  allocate x, 0\n")
    14489     (write _test-input-stream "}\n")
    14490     # convert
    14491     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14492     # registers except esp clobbered at this point
    14493     # restore ed
    14494     89/<- %edx 4/r32/esp
    14495     (flush _test-output-buffered-file)
    14496     (flush _test-error-buffered-file)
    14497 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14503     # check output
    14504     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
    14505     (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")
    14506     # check that stop(1) was called
    14507     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
    14508     # don't restore from ebp
    14509     81 0/subop/add %esp 8/imm32
    14510     # . epilogue
    14511     5d/pop-to-ebp
    14512     c3/return
    14513
    14514 test-allocate-with-output:
    14515     # . prologue
    14516     55/push-ebp
    14517     89/<- %ebp 4/r32/esp
    14518     # setup
    14519     (clear-stream _test-input-stream)
    14520     (clear-stream $_test-input-buffered-file->buffer)
    14521     (clear-stream _test-output-stream)
    14522     (clear-stream $_test-output-buffered-file->buffer)
    14523     (clear-stream _test-error-stream)
    14524     (clear-stream $_test-error-buffered-file->buffer)
    14525     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14526     68/push 0/imm32
    14527     68/push 0/imm32
    14528     89/<- %edx 4/r32/esp
    14529     (tailor-exit-descriptor %edx 0x10)
    14530     #
    14531     (write _test-input-stream "fn foo {\n")
    14532     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14533     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14534     (write _test-input-stream "  x <- allocate y\n")
    14535     (write _test-input-stream "}\n")
    14536     # convert
    14537     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14538     # registers except esp clobbered at this point
    14539     # restore ed
    14540     89/<- %edx 4/r32/esp
    14541     (flush _test-output-buffered-file)
    14542     (flush _test-error-buffered-file)
    14543 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14549     # check output
    14550     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
    14551     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
    14552     # check that stop(1) was called
    14553     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
    14554     # don't restore from ebp
    14555     81 0/subop/add %esp 8/imm32
    14556     # . epilogue
    14557     5d/pop-to-ebp
    14558     c3/return
    14559
    14560 test-allocate-non-addr:
    14561     # . prologue
    14562     55/push-ebp
    14563     89/<- %ebp 4/r32/esp
    14564     # setup
    14565     (clear-stream _test-input-stream)
    14566     (clear-stream $_test-input-buffered-file->buffer)
    14567     (clear-stream _test-output-stream)
    14568     (clear-stream $_test-output-buffered-file->buffer)
    14569     (clear-stream _test-error-stream)
    14570     (clear-stream $_test-error-buffered-file->buffer)
    14571     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14572     68/push 0/imm32
    14573     68/push 0/imm32
    14574     89/<- %edx 4/r32/esp
    14575     (tailor-exit-descriptor %edx 0x10)
    14576     #
    14577     (write _test-input-stream "fn foo {\n")
    14578     (write _test-input-stream "  var y: (handle int)\n")
    14579     (write _test-input-stream "  allocate y\n")
    14580     (write _test-input-stream "}\n")
    14581     # convert
    14582     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14583     # registers except esp clobbered at this point
    14584     # restore ed
    14585     89/<- %edx 4/r32/esp
    14586     (flush _test-output-buffered-file)
    14587     (flush _test-error-buffered-file)
    14588 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14594     # check output
    14595     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
    14596     (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")
    14597     # check that stop(1) was called
    14598     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
    14599     # don't restore from ebp
    14600     81 0/subop/add %esp 8/imm32
    14601     # . epilogue
    14602     5d/pop-to-ebp
    14603     c3/return
    14604
    14605 test-allocate-non-addr-handle:
    14606     # . prologue
    14607     55/push-ebp
    14608     89/<- %ebp 4/r32/esp
    14609     # setup
    14610     (clear-stream _test-input-stream)
    14611     (clear-stream $_test-input-buffered-file->buffer)
    14612     (clear-stream _test-output-stream)
    14613     (clear-stream $_test-output-buffered-file->buffer)
    14614     (clear-stream _test-error-stream)
    14615     (clear-stream $_test-error-buffered-file->buffer)
    14616     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14617     68/push 0/imm32
    14618     68/push 0/imm32
    14619     89/<- %edx 4/r32/esp
    14620     (tailor-exit-descriptor %edx 0x10)
    14621     #
    14622     (write _test-input-stream "fn foo {\n")
    14623     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14624     (write _test-input-stream "  allocate y\n")
    14625     (write _test-input-stream "}\n")
    14626     # convert
    14627     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14628     # registers except esp clobbered at this point
    14629     # restore ed
    14630     89/<- %edx 4/r32/esp
    14631     (flush _test-output-buffered-file)
    14632     (flush _test-error-buffered-file)
    14633 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14639     # check output
    14640     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
    14641     (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")
    14642     # check that stop(1) was called
    14643     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
    14644     # don't restore from ebp
    14645     81 0/subop/add %esp 8/imm32
    14646     # . epilogue
    14647     5d/pop-to-ebp
    14648     c3/return
    14649
    14650 test-allocate-deref-address:
    14651     # . prologue
    14652     55/push-ebp
    14653     89/<- %ebp 4/r32/esp
    14654     # setup
    14655     (clear-stream _test-input-stream)
    14656     (clear-stream $_test-input-buffered-file->buffer)
    14657     (clear-stream _test-output-stream)
    14658     (clear-stream $_test-output-buffered-file->buffer)
    14659     #
    14660     (write _test-input-stream "fn foo {\n")
    14661     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
    14662     (write _test-input-stream "  allocate *y\n")
    14663     (write _test-input-stream "}\n")
    14664     # convert
    14665     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14666     (flush _test-output-buffered-file)
    14667     # no errors
    14668     # . epilogue
    14669     5d/pop-to-ebp
    14670     c3/return
    14671
    14672 test-populate-with-no-inout:
    14673     # . prologue
    14674     55/push-ebp
    14675     89/<- %ebp 4/r32/esp
    14676     # setup
    14677     (clear-stream _test-input-stream)
    14678     (clear-stream $_test-input-buffered-file->buffer)
    14679     (clear-stream _test-output-stream)
    14680     (clear-stream $_test-output-buffered-file->buffer)
    14681     (clear-stream _test-error-stream)
    14682     (clear-stream $_test-error-buffered-file->buffer)
    14683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14684     68/push 0/imm32
    14685     68/push 0/imm32
    14686     89/<- %edx 4/r32/esp
    14687     (tailor-exit-descriptor %edx 0x10)
    14688     #
    14689     (write _test-input-stream "fn foo {\n")
    14690     (write _test-input-stream "  populate\n")
    14691     (write _test-input-stream "}\n")
    14692     # convert
    14693     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14694     # registers except esp clobbered at this point
    14695     # restore ed
    14696     89/<- %edx 4/r32/esp
    14697     (flush _test-output-buffered-file)
    14698     (flush _test-error-buffered-file)
    14699 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14705     # check output
    14706     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
    14707     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
    14708     # check that stop(1) was called
    14709     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
    14710     # don't restore from ebp
    14711     81 0/subop/add %esp 8/imm32
    14712     # . epilogue
    14713     5d/pop-to-ebp
    14714     c3/return
    14715
    14716 test-populate-with-too-many-inouts:
    14717     # . prologue
    14718     55/push-ebp
    14719     89/<- %ebp 4/r32/esp
    14720     # setup
    14721     (clear-stream _test-input-stream)
    14722     (clear-stream $_test-input-buffered-file->buffer)
    14723     (clear-stream _test-output-stream)
    14724     (clear-stream $_test-output-buffered-file->buffer)
    14725     (clear-stream _test-error-stream)
    14726     (clear-stream $_test-error-buffered-file->buffer)
    14727     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14728     68/push 0/imm32
    14729     68/push 0/imm32
    14730     89/<- %edx 4/r32/esp
    14731     (tailor-exit-descriptor %edx 0x10)
    14732     #
    14733     (write _test-input-stream "fn foo {\n")
    14734     (write _test-input-stream "  var x: (addr handle int)\n")
    14735     (write _test-input-stream "  populate x, 3, 0\n")
    14736     (write _test-input-stream "}\n")
    14737     # convert
    14738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14739     # registers except esp clobbered at this point
    14740     # restore ed
    14741     89/<- %edx 4/r32/esp
    14742     (flush _test-output-buffered-file)
    14743     (flush _test-error-buffered-file)
    14744 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14750     # check output
    14751     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
    14752     (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")
    14753     # check that stop(1) was called
    14754     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
    14755     # don't restore from ebp
    14756     81 0/subop/add %esp 8/imm32
    14757     # . epilogue
    14758     5d/pop-to-ebp
    14759     c3/return
    14760
    14761 test-populate-with-output:
    14762     # . prologue
    14763     55/push-ebp
    14764     89/<- %ebp 4/r32/esp
    14765     # setup
    14766     (clear-stream _test-input-stream)
    14767     (clear-stream $_test-input-buffered-file->buffer)
    14768     (clear-stream _test-output-stream)
    14769     (clear-stream $_test-output-buffered-file->buffer)
    14770     (clear-stream _test-error-stream)
    14771     (clear-stream $_test-error-buffered-file->buffer)
    14772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14773     68/push 0/imm32
    14774     68/push 0/imm32
    14775     89/<- %edx 4/r32/esp
    14776     (tailor-exit-descriptor %edx 0x10)
    14777     #
    14778     (write _test-input-stream "fn foo {\n")
    14779     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14780     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14781     (write _test-input-stream "  x <- populate y\n")
    14782     (write _test-input-stream "}\n")
    14783     # convert
    14784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14785     # registers except esp clobbered at this point
    14786     # restore ed
    14787     89/<- %edx 4/r32/esp
    14788     (flush _test-output-buffered-file)
    14789     (flush _test-error-buffered-file)
    14790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14796     # check output
    14797     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
    14798     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
    14799     # check that stop(1) was called
    14800     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
    14801     # don't restore from ebp
    14802     81 0/subop/add %esp 8/imm32
    14803     # . epilogue
    14804     5d/pop-to-ebp
    14805     c3/return
    14806
    14807 test-populate-non-addr:
    14808     # . prologue
    14809     55/push-ebp
    14810     89/<- %ebp 4/r32/esp
    14811     # setup
    14812     (clear-stream _test-input-stream)
    14813     (clear-stream $_test-input-buffered-file->buffer)
    14814     (clear-stream _test-output-stream)
    14815     (clear-stream $_test-output-buffered-file->buffer)
    14816     (clear-stream _test-error-stream)
    14817     (clear-stream $_test-error-buffered-file->buffer)
    14818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14819     68/push 0/imm32
    14820     68/push 0/imm32
    14821     89/<- %edx 4/r32/esp
    14822     (tailor-exit-descriptor %edx 0x10)
    14823     #
    14824     (write _test-input-stream "fn foo {\n")
    14825     (write _test-input-stream "  var y: (handle int)\n")
    14826     (write _test-input-stream "  populate y, 3\n")
    14827     (write _test-input-stream "}\n")
    14828     # convert
    14829     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14830     # registers except esp clobbered at this point
    14831     # restore ed
    14832     89/<- %edx 4/r32/esp
    14833     (flush _test-output-buffered-file)
    14834     (flush _test-error-buffered-file)
    14835 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14841     # check output
    14842     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
    14843     (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")
    14844     # check that stop(1) was called
    14845     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
    14846     # don't restore from ebp
    14847     81 0/subop/add %esp 8/imm32
    14848     # . epilogue
    14849     5d/pop-to-ebp
    14850     c3/return
    14851
    14852 test-populate-non-addr-handle:
    14853     # . prologue
    14854     55/push-ebp
    14855     89/<- %ebp 4/r32/esp
    14856     # setup
    14857     (clear-stream _test-input-stream)
    14858     (clear-stream $_test-input-buffered-file->buffer)
    14859     (clear-stream _test-output-stream)
    14860     (clear-stream $_test-output-buffered-file->buffer)
    14861     (clear-stream _test-error-stream)
    14862     (clear-stream $_test-error-buffered-file->buffer)
    14863     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14864     68/push 0/imm32
    14865     68/push 0/imm32
    14866     89/<- %edx 4/r32/esp
    14867     (tailor-exit-descriptor %edx 0x10)
    14868     #
    14869     (write _test-input-stream "fn foo {\n")
    14870     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14871     (write _test-input-stream "  populate y, 3\n")
    14872     (write _test-input-stream "}\n")
    14873     # convert
    14874     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14875     # registers except esp clobbered at this point
    14876     # restore ed
    14877     89/<- %edx 4/r32/esp
    14878     (flush _test-output-buffered-file)
    14879     (flush _test-error-buffered-file)
    14880 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14886     # check output
    14887     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
    14888     (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")
    14889     # check that stop(1) was called
    14890     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
    14891     # don't restore from ebp
    14892     81 0/subop/add %esp 8/imm32
    14893     # . epilogue
    14894     5d/pop-to-ebp
    14895     c3/return
    14896
    14897 test-populate-non-addr-handle-array:
    14898     # . prologue
    14899     55/push-ebp
    14900     89/<- %ebp 4/r32/esp
    14901     # setup
    14902     (clear-stream _test-input-stream)
    14903     (clear-stream $_test-input-buffered-file->buffer)
    14904     (clear-stream _test-output-stream)
    14905     (clear-stream $_test-output-buffered-file->buffer)
    14906     (clear-stream _test-error-stream)
    14907     (clear-stream $_test-error-buffered-file->buffer)
    14908     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14909     68/push 0/imm32
    14910     68/push 0/imm32
    14911     89/<- %edx 4/r32/esp
    14912     (tailor-exit-descriptor %edx 0x10)
    14913     #
    14914     (write _test-input-stream "fn foo {\n")
    14915     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14916     (write _test-input-stream "  populate y, 3\n")
    14917     (write _test-input-stream "}\n")
    14918     # convert
    14919     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14920     # registers except esp clobbered at this point
    14921     # restore ed
    14922     89/<- %edx 4/r32/esp
    14923     (flush _test-output-buffered-file)
    14924     (flush _test-error-buffered-file)
    14925 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14931     # check output
    14932     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
    14933     (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")
    14934     # check that stop(1) was called
    14935     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
    14936     # don't restore from ebp
    14937     81 0/subop/add %esp 8/imm32
    14938     # . epilogue
    14939     5d/pop-to-ebp
    14940     c3/return
    14941
    14942 test-populate-deref-address:
    14943     # . prologue
    14944     55/push-ebp
    14945     89/<- %ebp 4/r32/esp
    14946     # setup
    14947     (clear-stream _test-input-stream)
    14948     (clear-stream $_test-input-buffered-file->buffer)
    14949     (clear-stream _test-output-stream)
    14950     (clear-stream $_test-output-buffered-file->buffer)
    14951     #
    14952     (write _test-input-stream "fn foo {\n")
    14953     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
    14954     (write _test-input-stream "  populate *y, 3\n")
    14955     (write _test-input-stream "}\n")
    14956     # convert
    14957     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14958     (flush _test-output-buffered-file)
    14959     # no errors
    14960     # . epilogue
    14961     5d/pop-to-ebp
    14962     c3/return
    14963
    14964 test-populate-stream-with-no-inout:
    14965     # . prologue
    14966     55/push-ebp
    14967     89/<- %ebp 4/r32/esp
    14968     # setup
    14969     (clear-stream _test-input-stream)
    14970     (clear-stream $_test-input-buffered-file->buffer)
    14971     (clear-stream _test-output-stream)
    14972     (clear-stream $_test-output-buffered-file->buffer)
    14973     (clear-stream _test-error-stream)
    14974     (clear-stream $_test-error-buffered-file->buffer)
    14975     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14976     68/push 0/imm32
    14977     68/push 0/imm32
    14978     89/<- %edx 4/r32/esp
    14979     (tailor-exit-descriptor %edx 0x10)
    14980     #
    14981     (write _test-input-stream "fn foo {\n")
    14982     (write _test-input-stream "  populate-stream\n")
    14983     (write _test-input-stream "}\n")
    14984     # convert
    14985     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14986     # registers except esp clobbered at this point
    14987     # restore ed
    14988     89/<- %edx 4/r32/esp
    14989     (flush _test-output-buffered-file)
    14990     (flush _test-error-buffered-file)
    14991 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14997     # check output
    14998     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
    14999     (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")
    15000     # check that stop(1) was called
    15001     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
    15002     # don't restore from ebp
    15003     81 0/subop/add %esp 8/imm32
    15004     # . epilogue
    15005     5d/pop-to-ebp
    15006     c3/return
    15007
    15008 test-populate-stream-with-too-many-inouts:
    15009     # . prologue
    15010     55/push-ebp
    15011     89/<- %ebp 4/r32/esp
    15012     # setup
    15013     (clear-stream _test-input-stream)
    15014     (clear-stream $_test-input-buffered-file->buffer)
    15015     (clear-stream _test-output-stream)
    15016     (clear-stream $_test-output-buffered-file->buffer)
    15017     (clear-stream _test-error-stream)
    15018     (clear-stream $_test-error-buffered-file->buffer)
    15019     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15020     68/push 0/imm32
    15021     68/push 0/imm32
    15022     89/<- %edx 4/r32/esp
    15023     (tailor-exit-descriptor %edx 0x10)
    15024     #
    15025     (write _test-input-stream "fn foo {\n")
    15026     (write _test-input-stream "  var x: (addr handle int)\n")
    15027     (write _test-input-stream "  populate-stream x, 3, 0\n")
    15028     (write _test-input-stream "}\n")
    15029     # convert
    15030     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15031     # registers except esp clobbered at this point
    15032     # restore ed
    15033     89/<- %edx 4/r32/esp
    15034     (flush _test-output-buffered-file)
    15035     (flush _test-error-buffered-file)
    15036 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15042     # check output
    15043     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
    15044     (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")
    15045     # check that stop(1) was called
    15046     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
    15047     # don't restore from ebp
    15048     81 0/subop/add %esp 8/imm32
    15049     # . epilogue
    15050     5d/pop-to-ebp
    15051     c3/return
    15052
    15053 test-populate-stream-with-output:
    15054     # . prologue
    15055     55/push-ebp
    15056     89/<- %ebp 4/r32/esp
    15057     # setup
    15058     (clear-stream _test-input-stream)
    15059     (clear-stream $_test-input-buffered-file->buffer)
    15060     (clear-stream _test-output-stream)
    15061     (clear-stream $_test-output-buffered-file->buffer)
    15062     (clear-stream _test-error-stream)
    15063     (clear-stream $_test-error-buffered-file->buffer)
    15064     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15065     68/push 0/imm32
    15066     68/push 0/imm32
    15067     89/<- %edx 4/r32/esp
    15068     (tailor-exit-descriptor %edx 0x10)
    15069     #
    15070     (write _test-input-stream "fn foo {\n")
    15071     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    15072     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15073     (write _test-input-stream "  x <- populate-stream y\n")
    15074     (write _test-input-stream "}\n")
    15075     # convert
    15076     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15077     # registers except esp clobbered at this point
    15078     # restore ed
    15079     89/<- %edx 4/r32/esp
    15080     (flush _test-output-buffered-file)
    15081     (flush _test-error-buffered-file)
    15082 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15088     # check output
    15089     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
    15090     (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")
    15091     # check that stop(1) was called
    15092     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
    15093     # don't restore from ebp
    15094     81 0/subop/add %esp 8/imm32
    15095     # . epilogue
    15096     5d/pop-to-ebp
    15097     c3/return
    15098
    15099 test-populate-stream-non-addr:
    15100     # . prologue
    15101     55/push-ebp
    15102     89/<- %ebp 4/r32/esp
    15103     # setup
    15104     (clear-stream _test-input-stream)
    15105     (clear-stream $_test-input-buffered-file->buffer)
    15106     (clear-stream _test-output-stream)
    15107     (clear-stream $_test-output-buffered-file->buffer)
    15108     (clear-stream _test-error-stream)
    15109     (clear-stream $_test-error-buffered-file->buffer)
    15110     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15111     68/push 0/imm32
    15112     68/push 0/imm32
    15113     89/<- %edx 4/r32/esp
    15114     (tailor-exit-descriptor %edx 0x10)
    15115     #
    15116     (write _test-input-stream "fn foo {\n")
    15117     (write _test-input-stream "  var y: (handle int)\n")
    15118     (write _test-input-stream "  populate-stream y, 3\n")
    15119     (write _test-input-stream "}\n")
    15120     # convert
    15121     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15122     # registers except esp clobbered at this point
    15123     # restore ed
    15124     89/<- %edx 4/r32/esp
    15125     (flush _test-output-buffered-file)
    15126     (flush _test-error-buffered-file)
    15127 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15133     # check output
    15134     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
    15135     (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")
    15136     # check that stop(1) was called
    15137     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
    15138     # don't restore from ebp
    15139     81 0/subop/add %esp 8/imm32
    15140     # . epilogue
    15141     5d/pop-to-ebp
    15142     c3/return
    15143
    15144 test-populate-stream-non-addr-handle:
    15145     # . prologue
    15146     55/push-ebp
    15147     89/<- %ebp 4/r32/esp
    15148     # setup
    15149     (clear-stream _test-input-stream)
    15150     (clear-stream $_test-input-buffered-file->buffer)
    15151     (clear-stream _test-output-stream)
    15152     (clear-stream $_test-output-buffered-file->buffer)
    15153     (clear-stream _test-error-stream)
    15154     (clear-stream $_test-error-buffered-file->buffer)
    15155     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15156     68/push 0/imm32
    15157     68/push 0/imm32
    15158     89/<- %edx 4/r32/esp
    15159     (tailor-exit-descriptor %edx 0x10)
    15160     #
    15161     (write _test-input-stream "fn foo {\n")
    15162     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    15163     (write _test-input-stream "  populate-stream y, 3\n")
    15164     (write _test-input-stream "}\n")
    15165     # convert
    15166     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15167     # registers except esp clobbered at this point
    15168     # restore ed
    15169     89/<- %edx 4/r32/esp
    15170     (flush _test-output-buffered-file)
    15171     (flush _test-error-buffered-file)
    15172 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15178     # check output
    15179     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
    15180     (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")
    15181     # check that stop(1) was called
    15182     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
    15183     # don't restore from ebp
    15184     81 0/subop/add %esp 8/imm32
    15185     # . epilogue
    15186     5d/pop-to-ebp
    15187     c3/return
    15188
    15189 test-populate-stream-non-addr-handle-stream:
    15190     # . prologue
    15191     55/push-ebp
    15192     89/<- %ebp 4/r32/esp
    15193     # setup
    15194     (clear-stream _test-input-stream)
    15195     (clear-stream $_test-input-buffered-file->buffer)
    15196     (clear-stream _test-output-stream)
    15197     (clear-stream $_test-output-buffered-file->buffer)
    15198     (clear-stream _test-error-stream)
    15199     (clear-stream $_test-error-buffered-file->buffer)
    15200     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15201     68/push 0/imm32
    15202     68/push 0/imm32
    15203     89/<- %edx 4/r32/esp
    15204     (tailor-exit-descriptor %edx 0x10)
    15205     #
    15206     (write _test-input-stream "fn foo {\n")
    15207     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15208     (write _test-input-stream "  populate-stream y, 3\n")
    15209     (write _test-input-stream "}\n")
    15210     # convert
    15211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15212     # registers except esp clobbered at this point
    15213     # restore ed
    15214     89/<- %edx 4/r32/esp
    15215     (flush _test-output-buffered-file)
    15216     (flush _test-error-buffered-file)
    15217 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15223     # check output
    15224     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
    15225     (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")
    15226     # check that stop(1) was called
    15227     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
    15228     # don't restore from ebp
    15229     81 0/subop/add %esp 8/imm32
    15230     # . epilogue
    15231     5d/pop-to-ebp
    15232     c3/return
    15233
    15234 test-populate-stream-deref-address:
    15235     # . prologue
    15236     55/push-ebp
    15237     89/<- %ebp 4/r32/esp
    15238     # setup
    15239     (clear-stream _test-input-stream)
    15240     (clear-stream $_test-input-buffered-file->buffer)
    15241     (clear-stream _test-output-stream)
    15242     (clear-stream $_test-output-buffered-file->buffer)
    15243     #
    15244     (write _test-input-stream "fn foo {\n")
    15245     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
    15246     (write _test-input-stream "  populate-stream *y, 3\n")
    15247     (write _test-input-stream "}\n")
    15248     # convert
    15249     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15250     (flush _test-output-buffered-file)
    15251     # no errors
    15252     # . epilogue
    15253     5d/pop-to-ebp
    15254     c3/return
    15255
    15256 test-convert-with-no-inout:
    15257     # . prologue
    15258     55/push-ebp
    15259     89/<- %ebp 4/r32/esp
    15260     # setup
    15261     (clear-stream _test-input-stream)
    15262     (clear-stream $_test-input-buffered-file->buffer)
    15263     (clear-stream _test-output-stream)
    15264     (clear-stream $_test-output-buffered-file->buffer)
    15265     (clear-stream _test-error-stream)
    15266     (clear-stream $_test-error-buffered-file->buffer)
    15267     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15268     68/push 0/imm32
    15269     68/push 0/imm32
    15270     89/<- %edx 4/r32/esp
    15271     (tailor-exit-descriptor %edx 0x10)
    15272     #
    15273     (write _test-input-stream "fn foo {\n")
    15274     (write _test-input-stream "  var x/eax: int <- convert\n")
    15275     (write _test-input-stream "}\n")
    15276     # convert
    15277     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15278     # registers except esp clobbered at this point
    15279     # restore ed
    15280     89/<- %edx 4/r32/esp
    15281     (flush _test-output-buffered-file)
    15282     (flush _test-error-buffered-file)
    15283 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15289     # check output
    15290     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
    15291     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
    15292     # check that stop(1) was called
    15293     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
    15294     # don't restore from ebp
    15295     81 0/subop/add %esp 8/imm32
    15296     # . epilogue
    15297     5d/pop-to-ebp
    15298     c3/return
    15299
    15300 test-convert-with-multiple-inouts:
    15301     # . prologue
    15302     55/push-ebp
    15303     89/<- %ebp 4/r32/esp
    15304     # setup
    15305     (clear-stream _test-input-stream)
    15306     (clear-stream $_test-input-buffered-file->buffer)
    15307     (clear-stream _test-output-stream)
    15308     (clear-stream $_test-output-buffered-file->buffer)
    15309     (clear-stream _test-error-stream)
    15310     (clear-stream $_test-error-buffered-file->buffer)
    15311     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15312     68/push 0/imm32
    15313     68/push 0/imm32
    15314     89/<- %edx 4/r32/esp
    15315     (tailor-exit-descriptor %edx 0x10)
    15316     #
    15317     (write _test-input-stream "fn foo {\n")
    15318     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
    15319     (write _test-input-stream "}\n")
    15320     # convert
    15321     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15322     # registers except esp clobbered at this point
    15323     # restore ed
    15324     89/<- %edx 4/r32/esp
    15325     (flush _test-output-buffered-file)
    15326     (flush _test-error-buffered-file)
    15327 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15333     # check output
    15334     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
    15335     (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")
    15336     # check that stop(1) was called
    15337     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
    15338     # don't restore from ebp
    15339     81 0/subop/add %esp 8/imm32
    15340     # . epilogue
    15341     5d/pop-to-ebp
    15342     c3/return
    15343
    15344 test-convert-with-no-output:
    15345     # . prologue
    15346     55/push-ebp
    15347     89/<- %ebp 4/r32/esp
    15348     # setup
    15349     (clear-stream _test-input-stream)
    15350     (clear-stream $_test-input-buffered-file->buffer)
    15351     (clear-stream _test-output-stream)
    15352     (clear-stream $_test-output-buffered-file->buffer)
    15353     (clear-stream _test-error-stream)
    15354     (clear-stream $_test-error-buffered-file->buffer)
    15355     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15356     68/push 0/imm32
    15357     68/push 0/imm32
    15358     89/<- %edx 4/r32/esp
    15359     (tailor-exit-descriptor %edx 0x10)
    15360     #
    15361     (write _test-input-stream "fn foo {\n")
    15362     (write _test-input-stream "  convert 0\n")
    15363     (write _test-input-stream "}\n")
    15364     # convert
    15365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15366     # registers except esp clobbered at this point
    15367     # restore ed
    15368     89/<- %edx 4/r32/esp
    15369     (flush _test-output-buffered-file)
    15370     (flush _test-error-buffered-file)
    15371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15377     # check output
    15378     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
    15379     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
    15380     # check that stop(1) was called
    15381     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
    15382     # don't restore from ebp
    15383     81 0/subop/add %esp 8/imm32
    15384     # . epilogue
    15385     5d/pop-to-ebp
    15386     c3/return
    15387
    15388 test-convert-with-multiple-outputs:
    15389     # . prologue
    15390     55/push-ebp
    15391     89/<- %ebp 4/r32/esp
    15392     # setup
    15393     (clear-stream _test-input-stream)
    15394     (clear-stream $_test-input-buffered-file->buffer)
    15395     (clear-stream _test-output-stream)
    15396     (clear-stream $_test-output-buffered-file->buffer)
    15397     (clear-stream _test-error-stream)
    15398     (clear-stream $_test-error-buffered-file->buffer)
    15399     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15400     68/push 0/imm32
    15401     68/push 0/imm32
    15402     89/<- %edx 4/r32/esp
    15403     (tailor-exit-descriptor %edx 0x10)
    15404     #
    15405     (write _test-input-stream "fn foo {\n")
    15406     (write _test-input-stream "  var x/eax: int <- copy 0\n")
    15407     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
    15408     (write _test-input-stream "  x, y <- convert 0\n")
    15409     (write _test-input-stream "}\n")
    15410     # convert
    15411     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15412     # registers except esp clobbered at this point
    15413     # restore ed
    15414     89/<- %edx 4/r32/esp
    15415     (flush _test-output-buffered-file)
    15416     (flush _test-error-buffered-file)
    15417 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15423     # check output
    15424     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
    15425     (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")
    15426     # check that stop(1) was called
    15427     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
    15428     # don't restore from ebp
    15429     81 0/subop/add %esp 8/imm32
    15430     # . epilogue
    15431     5d/pop-to-ebp
    15432     c3/return
    15433
    15434 test-convert-deref-address:
    15435     # . prologue
    15436     55/push-ebp
    15437     89/<- %ebp 4/r32/esp
    15438     # setup
    15439     (clear-stream _test-input-stream)
    15440     (clear-stream $_test-input-buffered-file->buffer)
    15441     (clear-stream _test-output-stream)
    15442     (clear-stream $_test-output-buffered-file->buffer)
    15443     #
    15444     (write _test-input-stream "fn foo {\n")
    15445     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    15446     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
    15447     (write _test-input-stream "}\n")
    15448     # convert
    15449     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15450     (flush _test-output-buffered-file)
    15451     # no errors
    15452     # . epilogue
    15453     5d/pop-to-ebp
    15454     c3/return
    15455
    15456 test-convert-to-non-register:
    15457     # . prologue
    15458     55/push-ebp
    15459     89/<- %ebp 4/r32/esp
    15460     # setup
    15461     (clear-stream _test-input-stream)
    15462     (clear-stream $_test-input-buffered-file->buffer)
    15463     (clear-stream _test-output-stream)
    15464     (clear-stream $_test-output-buffered-file->buffer)
    15465     (clear-stream _test-error-stream)
    15466     (clear-stream $_test-error-buffered-file->buffer)
    15467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15468     68/push 0/imm32
    15469     68/push 0/imm32
    15470     89/<- %edx 4/r32/esp
    15471     (tailor-exit-descriptor %edx 0x10)
    15472     #
    15473     (write _test-input-stream "fn foo {\n")
    15474     (write _test-input-stream "  var x: float\n")
    15475     (write _test-input-stream "  var y: int\n")
    15476     (write _test-input-stream "  x <- convert y\n")
    15477     (write _test-input-stream "}\n")
    15478     # convert
    15479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15480     # registers except esp clobbered at this point
    15481     # restore ed
    15482     89/<- %edx 4/r32/esp
    15483     (flush _test-output-buffered-file)
    15484     (flush _test-error-buffered-file)
    15485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15491     # check output
    15492     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
    15493     (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")
    15494     # check that stop(1) was called
    15495     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
    15496     # don't restore from ebp
    15497     81 0/subop/add %esp 8/imm32
    15498     # . epilogue
    15499     5d/pop-to-ebp
    15500     c3/return
    15501
    15502 test-convert-invalid-inout-type:
    15503     # . prologue
    15504     55/push-ebp
    15505     89/<- %ebp 4/r32/esp
    15506     # setup
    15507     (clear-stream _test-input-stream)
    15508     (clear-stream $_test-input-buffered-file->buffer)
    15509     (clear-stream _test-output-stream)
    15510     (clear-stream $_test-output-buffered-file->buffer)
    15511     (clear-stream _test-error-stream)
    15512     (clear-stream $_test-error-buffered-file->buffer)
    15513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15514     68/push 0/imm32
    15515     68/push 0/imm32
    15516     89/<- %edx 4/r32/esp
    15517     (tailor-exit-descriptor %edx 0x10)
    15518     #
    15519     (write _test-input-stream "fn foo {\n")
    15520     (write _test-input-stream "  var x: boolean\n")
    15521     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
    15522     (write _test-input-stream "}\n")
    15523     # convert
    15524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15525     # registers except esp clobbered at this point
    15526     # restore ed
    15527     89/<- %edx 4/r32/esp
    15528     (flush _test-output-buffered-file)
    15529     (flush _test-error-buffered-file)
    15530 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15536     # check output
    15537     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
    15538     (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")
    15539     # check that stop(1) was called
    15540     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
    15541     # don't restore from ebp
    15542     81 0/subop/add %esp 8/imm32
    15543     # . epilogue
    15544     5d/pop-to-ebp
    15545     c3/return
    15546
    15547 test-convert-invalid-output-type:
    15548     # . prologue
    15549     55/push-ebp
    15550     89/<- %ebp 4/r32/esp
    15551     # setup
    15552     (clear-stream _test-input-stream)
    15553     (clear-stream $_test-input-buffered-file->buffer)
    15554     (clear-stream _test-output-stream)
    15555     (clear-stream $_test-output-buffered-file->buffer)
    15556     (clear-stream _test-error-stream)
    15557     (clear-stream $_test-error-buffered-file->buffer)
    15558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15559     68/push 0/imm32
    15560     68/push 0/imm32
    15561     89/<- %edx 4/r32/esp
    15562     (tailor-exit-descriptor %edx 0x10)
    15563     #
    15564     (write _test-input-stream "fn foo {\n")
    15565     (write _test-input-stream "  var x: float\n")
    15566     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
    15567     (write _test-input-stream "}\n")
    15568     # convert
    15569     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15570     # registers except esp clobbered at this point
    15571     # restore ed
    15572     89/<- %edx 4/r32/esp
    15573     (flush _test-output-buffered-file)
    15574     (flush _test-error-buffered-file)
    15575 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15581     # check output
    15582     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
    15583     (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")
    15584     # check that stop(1) was called
    15585     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
    15586     # don't restore from ebp
    15587     81 0/subop/add %esp 8/imm32
    15588     # . epilogue
    15589     5d/pop-to-ebp
    15590     c3/return
    15591
    15592 test-convert-int-to-int:
    15593     # . prologue
    15594     55/push-ebp
    15595     89/<- %ebp 4/r32/esp
    15596     # setup
    15597     (clear-stream _test-input-stream)
    15598     (clear-stream $_test-input-buffered-file->buffer)
    15599     (clear-stream _test-output-stream)
    15600     (clear-stream $_test-output-buffered-file->buffer)
    15601     (clear-stream _test-error-stream)
    15602     (clear-stream $_test-error-buffered-file->buffer)
    15603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15604     68/push 0/imm32
    15605     68/push 0/imm32
    15606     89/<- %edx 4/r32/esp
    15607     (tailor-exit-descriptor %edx 0x10)
    15608     #
    15609     (write _test-input-stream "fn foo {\n")
    15610     (write _test-input-stream "  var x: int\n")
    15611     (write _test-input-stream "  var y/eax: int <- convert x\n")
    15612     (write _test-input-stream "}\n")
    15613     # convert
    15614     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15615     # registers except esp clobbered at this point
    15616     # restore ed
    15617     89/<- %edx 4/r32/esp
    15618     (flush _test-output-buffered-file)
    15619     (flush _test-error-buffered-file)
    15620 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15626     # check output
    15627     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
    15628     (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")
    15629     # check that stop(1) was called
    15630     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
    15631     # don't restore from ebp
    15632     81 0/subop/add %esp 8/imm32
    15633     # . epilogue
    15634     5d/pop-to-ebp
    15635     c3/return
    15636
    15637 test-convert-float-to-float:
    15638     # . prologue
    15639     55/push-ebp
    15640     89/<- %ebp 4/r32/esp
    15641     # setup
    15642     (clear-stream _test-input-stream)
    15643     (clear-stream $_test-input-buffered-file->buffer)
    15644     (clear-stream _test-output-stream)
    15645     (clear-stream $_test-output-buffered-file->buffer)
    15646     (clear-stream _test-error-stream)
    15647     (clear-stream $_test-error-buffered-file->buffer)
    15648     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15649     68/push 0/imm32
    15650     68/push 0/imm32
    15651     89/<- %edx 4/r32/esp
    15652     (tailor-exit-descriptor %edx 0x10)
    15653     #
    15654     (write _test-input-stream "fn foo {\n")
    15655     (write _test-input-stream "  var x: float\n")
    15656     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
    15657     (write _test-input-stream "}\n")
    15658     # convert
    15659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15660     # registers except esp clobbered at this point
    15661     # restore ed
    15662     89/<- %edx 4/r32/esp
    15663     (flush _test-output-buffered-file)
    15664     (flush _test-error-buffered-file)
    15665 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15671     # check output
    15672     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
    15673     (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")
    15674     # check that stop(1) was called
    15675     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
    15676     # don't restore from ebp
    15677     81 0/subop/add %esp 8/imm32
    15678     # . epilogue
    15679     5d/pop-to-ebp
    15680     c3/return
    15681
    15682 #######################################################
    15683 # Parsing
    15684 #######################################################
    15685
    15686 == data
    15687
    15688 # Global state added to each var record when parsing a function
    15689 Next-block-index:  # (addr int)
    15690     1/imm32
    15691
    15692 Curr-block-depth:  # (addr int)
    15693     1/imm32
    15694
    15695 == code
    15696
    15697 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    15698     # pseudocode
    15699     #   var curr-function: (addr handle function) = Program->functions
    15700     #   var curr-signature: (addr handle function) = Program->signatures
    15701     #   var curr-type: (addr handle typeinfo) = Program->types
    15702     #   var line: (stream byte 512)
    15703     #   var word-slice: slice
    15704     #   while true                                  # line loop
    15705     #     clear-stream(line)
    15706     #     read-line-buffered(in, line)
    15707     #     if (line->write == 0) break               # end of file
    15708     #     word-slice = next-mu-token(line)
    15709     #     if slice-empty?(word-slice)               # end of line
    15710     #       continue
    15711     #     else if slice-starts-with?(word-slice, "#")  # comment
    15712     #       continue                                # end of line
    15713     #     else if slice-equal?(word-slice, "fn")
    15714     #       var new-function: (handle function) = allocate(function)
    15715     #       var vars: (stack live-var 256)
    15716     #       populate-mu-function-header(line, new-function, vars)
    15717     #       populate-mu-function-body(in, new-function, vars)
    15718     #       assert(vars->top == 0)
    15719     #       *curr-function = new-function
    15720     #       curr-function = &new-function->next
    15721     #     else if slice-equal?(word-slice, "sig")
    15722     #       var new-function: (handle function) = allocate(function)
    15723     #       populate-mu-function-signature(line, new-function)
    15724     #       *curr-signature = new-function
    15725     #       curr-signature = &new-function->next
    15726     #     else if slice-equal?(word-slice, "type")
    15727     #       word-slice = next-mu-token(line)
    15728     #       type-id = pos-or-insert-slice(Type-id, word-slice)
    15729     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
    15730     #       assert(next-word(line) == "{")
    15731     #       populate-mu-type(in, new-type)
    15732     #     else
    15733     #       abort()
    15734     #
    15735     # . prologue
    15736     55/push-ebp
    15737     89/<- %ebp 4/r32/esp
    15738     # var curr-signature: (addr handle function) at *(ebp-4)
    15739     68/push _Program-signatures/imm32
    15740     # . save registers
    15741     50/push-eax
    15742     51/push-ecx
    15743     52/push-edx
    15744     53/push-ebx
    15745     56/push-esi
    15746     57/push-edi
    15747     # var line/ecx: (stream byte 512)
    15748     81 5/subop/subtract %esp 0x200/imm32
    15749     68/push 0x200/imm32/size
    15750     68/push 0/imm32/read
    15751     68/push 0/imm32/write
    15752     89/<- %ecx 4/r32/esp
    15753     # var word-slice/edx: slice
    15754     68/push 0/imm32/end
    15755     68/push 0/imm32/start
    15756     89/<- %edx 4/r32/esp
    15757     # var curr-function/edi: (addr handle function)
    15758     bf/copy-to-edi _Program-functions/imm32
    15759     # var vars/ebx: (stack live-var 256)
    15760     81 5/subop/subtract %esp 0xc00/imm32
    15761     68/push 0xc00/imm32/size
    15762     68/push 0/imm32/top
    15763     89/<- %ebx 4/r32/esp
    15764     {
    15765 $parse-mu:line-loop:
    15766       (clear-stream %ecx)
    15767       (read-line-buffered *(ebp+8) %ecx)
    15768       # if (line->write == 0) break
    15769       81 7/subop/compare *ecx 0/imm32
    15770       0f 84/jump-if-= break/disp32
    15771 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
    15777       (next-mu-token %ecx %edx)
    15778       # if slice-empty?(word-slice) continue
    15779       (slice-empty? %edx)  # => eax
    15780       3d/compare-eax-and 0/imm32/false
    15781       0f 85/jump-if-!= loop/disp32
    15782       # if (*word-slice->start == "#") continue
    15783       # . eax = *word-slice->start
    15784       8b/-> *edx 0/r32/eax
    15785       8a/copy-byte *eax 0/r32/AL
    15786       81 4/subop/and %eax 0xff/imm32
    15787       # . if (eax == '#') continue
    15788       3d/compare-eax-and 0x23/imm32/hash
    15789       0f 84/jump-if-= loop/disp32
    15790       # if (slice-equal?(word-slice, "fn")) parse a function
    15791       {
    15792 $parse-mu:fn:
    15793         (slice-equal? %edx "fn")  # => eax
    15794         3d/compare-eax-and 0/imm32/false
    15795         0f 84/jump-if-= break/disp32
    15796         # var new-function/esi: (handle function)
    15797         68/push 0/imm32
    15798         68/push 0/imm32
    15799         89/<- %esi 4/r32/esp
    15800         # populate-mu-function(line, in, vars, new-function)
    15801         (allocate Heap *Function-size %esi)
    15802         # var new-function-addr/eax: (addr function)
    15803         (lookup *esi *(esi+4))  # => eax
    15804         # initialize vars
    15805         (clear-stack %ebx)
    15806         #
    15807         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15808         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15809         # *curr-function = new-function
    15810         8b/-> *esi 0/r32/eax
    15811         89/<- *edi 0/r32/eax
    15812         8b/-> *(esi+4) 0/r32/eax
    15813         89/<- *(edi+4) 0/r32/eax
    15814         # curr-function = &new-function->next
    15815         # . var tmp/eax: (addr function) = lookup(new-function)
    15816         (lookup *esi *(esi+4))  # => eax
    15817         # . curr-function = &tmp->next
    15818         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15819         # reclaim new-function
    15820         81 0/subop/add %esp 8/imm32
    15821         #
    15822         e9/jump $parse-mu:line-loop/disp32
    15823       }
    15824       # if (slice-equal?(word-slice, "sig")) parse a function signature
    15825       # Function signatures are for providing types to SubX functions.
    15826       {
    15827 $parse-mu:sig:
    15828         (slice-equal? %edx "sig")  # => eax
    15829         3d/compare-eax-and 0/imm32/false
    15830         0f 84/jump-if-= break/disp32
    15831         # edi = curr-function
    15832         57/push-edi
    15833         8b/-> *(ebp-4) 7/r32/edi
    15834         # var new-function/esi: (handle function)
    15835         68/push 0/imm32
    15836         68/push 0/imm32
    15837         89/<- %esi 4/r32/esp
    15838         # populate-mu-function(line, in, vars, new-function)
    15839         (allocate Heap *Function-size %esi)
    15840         # var new-function-addr/eax: (addr function)
    15841         (lookup *esi *(esi+4))  # => eax
    15842         #
    15843         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
    15844         # *curr-signature = new-function
    15845         8b/-> *esi 0/r32/eax
    15846         89/<- *edi 0/r32/eax
    15847         8b/-> *(esi+4) 0/r32/eax
    15848         89/<- *(edi+4) 0/r32/eax
    15849         # curr-signature = &new-function->next
    15850         # . var tmp/eax: (addr function) = lookup(new-function)
    15851         (lookup *esi *(esi+4))  # => eax
    15852         # . curr-function = &tmp->next
    15853         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15854         # reclaim new-function
    15855         81 0/subop/add %esp 8/imm32
    15856         # save curr-function
    15857         89/<- *(ebp-4) 7/r32/edi
    15858         # restore edi
    15859         5f/pop-to-edi
    15860         #
    15861         e9/jump $parse-mu:line-loop/disp32
    15862       }
    15863       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
    15864       {
    15865 $parse-mu:type:
    15866         (slice-equal? %edx "type")  # => eax
    15867         3d/compare-eax-and 0/imm32
    15868         0f 84/jump-if-= break/disp32
    15869         (next-mu-token %ecx %edx)
    15870         # var type-id/eax: int
    15871         (pos-or-insert-slice Type-id %edx)  # => eax
    15872         # spill
    15873         51/push-ecx
    15874         # var new-type/ecx: (handle typeinfo)
    15875         68/push 0/imm32
    15876         68/push 0/imm32
    15877         89/<- %ecx 4/r32/esp
    15878         (find-or-create-typeinfo %eax %ecx)
    15879         #
    15880         (lookup *ecx *(ecx+4))  # => eax
    15881         # TODO: ensure that 'line' has nothing else but '{'
    15882 #? (dump-typeinfos "=== aaa\n")
    15883         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    15884 #? (dump-typeinfos "=== zzz\n")
    15885         # reclaim new-type
    15886         81 0/subop/add %esp 8/imm32
    15887         # restore
    15888         59/pop-to-ecx
    15889         e9/jump $parse-mu:line-loop/disp32
    15890       }
    15891       # otherwise abort
    15892       e9/jump $parse-mu:error1/disp32
    15893     } # end line loop
    15894 $parse-mu:end:
    15895     # . reclaim locals
    15896     81 0/subop/add %esp 0x20c/imm32  # line
    15897     81 0/subop/add %esp 0xc08/imm32  # vars
    15898     81 0/subop/add %esp 8/imm32
    15899     # . restore registers
    15900     5f/pop-to-edi
    15901     5e/pop-to-esi
    15902     5b/pop-to-ebx
    15903     5a/pop-to-edx
    15904     59/pop-to-ecx
    15905     58/pop-to-eax
    15906     # . reclaim local
    15907     81 0/subop/add %esp 4/imm32
    15908     # . epilogue
    15909     89/<- %esp 5/r32/ebp
    15910     5d/pop-to-ebp
    15911     c3/return
    15912
    15913 $parse-mu:error1:
    15914     # error("unexpected top-level command: " word-slice "\n")
    15915     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
    15916     (write-slice-buffered *(ebp+0xc) %edx)
    15917     (write-buffered *(ebp+0xc) "\n")
    15918     (flush *(ebp+0xc))
    15919     (stop *(ebp+0x10) 1)
    15920     # never gets here
    15921
    15922 $parse-mu:error2:
    15923     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
    15924     (write-int32-hex-buffered *(ebp+0xc) *ebx)
    15925     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
    15926     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
    15927     (write-buffered *(ebp+0xc) "'\n")
    15928     (flush *(ebp+0xc))
    15929     (stop *(ebp+0x10) 1)
    15930     # never gets here
    15931
    15932 # scenarios considered:
    15933 # ✗ fn foo  # no block
    15934 # ✓ fn foo {
    15935 # ✗ fn foo { {
    15936 # ✗ fn foo { }
    15937 # ✗ fn foo { } {
    15938 # ✗ fn foo x {
    15939 # ✗ fn foo x: {
    15940 # ✓ fn foo x: int {
    15941 # ✓ fn foo x: int {
    15942 # ✓ fn foo x: int -> _/eax: int {
    15943 # TODO:
    15944 #   disallow outputs of type `(... addr ...)`
    15945 #   disallow inputs of type `(... addr ... addr ...)`
    15946 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)
    15947     # pseudocode:
    15948     #   var word-slice: slice
    15949     #   next-mu-token(first-line, word-slice)
    15950     #   if slice-empty?(word-slice) abort
    15951     #   assert(word-slice not in '{' '}' '->')
    15952     #   out->name = slice-to-string(word-slice)
    15953     #   ## inouts
    15954     #   while true
    15955     #     word-slice = next-mu-token(first-line)
    15956     #     if slice-empty?(word-slice) abort
    15957     #     if (word-slice == '{') goto done
    15958     #     if (word-slice == '->') break
    15959     #     assert(word-slice != '}')
    15960     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    15961     #     assert(v->register == null)
    15962     #     # v->block-depth is implicitly 0
    15963     #     out->inouts = append(v, out->inouts)
    15964     #     push(vars, {v, false})
    15965     #   ## outputs
    15966     #   while true
    15967     #     word-slice = next-mu-token(first-line)
    15968     #     if slice-empty?(word-slice) abort
    15969     #     if (word-slice == '{') break
    15970     #     assert(word-slice not in '}' '->')
    15971     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    15972     #     assert(v->register != null)
    15973     #     assert(v->name == "_")
    15974     #     out->outputs = append(v, out->outputs)
    15975     #   done:
    15976     #
    15977     # . prologue
    15978     55/push-ebp
    15979     89/<- %ebp 4/r32/esp
    15980     # . save registers
    15981     50/push-eax
    15982     51/push-ecx
    15983     52/push-edx
    15984     53/push-ebx
    15985     57/push-edi
    15986     # edi = out
    15987     8b/-> *(ebp+0xc) 7/r32/edi
    15988     # var word-slice/ecx: slice
    15989     68/push 0/imm32/end
    15990     68/push 0/imm32/start
    15991     89/<- %ecx 4/r32/esp
    15992     # var v/ebx: (handle var)
    15993     68/push 0/imm32
    15994     68/push 0/imm32
    15995     89/<- %ebx 4/r32/esp
    15996     # read function name
    15997     (next-mu-token *(ebp+8) %ecx)
    15998     # error checking
    15999     # if slice-empty?(word-slice) abort
    16000     (slice-empty? %ecx)  # => eax
    16001     3d/compare-eax-and 0/imm32/false
    16002     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16003     # if (word-slice == '{') abort
    16004     (slice-equal? %ecx "{")   # => eax
    16005     3d/compare-eax-and 0/imm32/false
    16006     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16007     # if (word-slice == '->') abort
    16008     (slice-equal? %ecx "->")   # => eax
    16009     3d/compare-eax-and 0/imm32/false
    16010     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16011     # if (word-slice == '}') abort
    16012     (slice-equal? %ecx "}")   # => eax
    16013     3d/compare-eax-and 0/imm32/false
    16014     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16015     # if word-slice already defined, abort
    16016     (function-exists? %ecx)  # => eax
    16017     3d/compare-eax-and 0/imm32/false
    16018     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
    16019     #
    16020     (slice-starts-with? %ecx "break")  # => eax
    16021     3d/compare-eax-and 0/imm32/false
    16022     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
    16023     (slice-starts-with? %ecx "loop")  # => eax
    16024     3d/compare-eax-and 0/imm32/false
    16025     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
    16026     (slice-equal? %ecx "lookup")  # => eax
    16027     3d/compare-eax-and 0/imm32/false
    16028     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
    16029     # save function name
    16030     (slice-to-string Heap %ecx %edi)  # Function-name
    16031     # save function inouts
    16032     {
    16033 $populate-mu-function-header:check-for-inout:
    16034       (next-mu-token *(ebp+8) %ecx)
    16035       # if slice-empty?(word-slice) abort
    16036       (slice-empty? %ecx)  # => eax
    16037       3d/compare-eax-and 0/imm32/false
    16038       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16039       # if (word-slice == '{') goto done
    16040       (slice-equal? %ecx "{")   # => eax
    16041       3d/compare-eax-and 0/imm32/false
    16042       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
    16043       # if (word-slice == '->') break
    16044       (slice-equal? %ecx "->")   # => eax
    16045       3d/compare-eax-and 0/imm32/false
    16046       0f 85/jump-if-!= break/disp32
    16047       # if (word-slice == '}') abort
    16048       (slice-equal? %ecx "}")   # => eax
    16049       3d/compare-eax-and 0/imm32/false
    16050       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16051       # v = parse-var-with-type(word-slice, first-line)
    16052       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16053       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16054       # if (v->register != null) abort
    16055       # . eax: (addr var) = lookup(v)
    16056       (lookup *ebx *(ebx+4))  # => eax
    16057       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16058       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
    16059       # if function name is not "main"
    16060       #    and v->type contains an 'addr' anywhere except the start, abort
    16061       {
    16062         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16063         (string-equal? %eax "main")  # => eax
    16064         3d/compare-eax-and 0/imm32/false
    16065         75/jump-if-!= break/disp8
    16066         (lookup *ebx *(ebx+4))  # => eax
    16067         (addr-payload-contains-addr? %eax)  # => eax
    16068         3d/compare-eax-and 0/imm32/false
    16069         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
    16070       }
    16071       # v->block-depth is implicitly 0
    16072       #
    16073       # out->inouts = append(v, out->inouts)
    16074       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16075       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16076       # push(vars, {v, false})
    16077       (push *(ebp+0x10) *ebx)
    16078       (push *(ebp+0x10) *(ebx+4))
    16079       (push *(ebp+0x10) 0)  # false
    16080       #
    16081       e9/jump loop/disp32
    16082     }
    16083     # save function outputs
    16084     {
    16085 $populate-mu-function-header:check-for-out:
    16086       (next-mu-token *(ebp+8) %ecx)
    16087       # if slice-empty?(word-slice) abort
    16088       (slice-empty? %ecx)  # => eax
    16089       3d/compare-eax-and 0/imm32/false
    16090       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16091       # if (word-slice == '{') break
    16092       (slice-equal? %ecx "{")   # => eax
    16093       3d/compare-eax-and 0/imm32/false
    16094       0f 85/jump-if-!= break/disp32
    16095       # if (word-slice == '->') abort
    16096       (slice-equal? %ecx "->")   # => eax
    16097       3d/compare-eax-and 0/imm32/false
    16098       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16099       # if (word-slice == '}') abort
    16100       (slice-equal? %ecx "}")   # => eax
    16101       3d/compare-eax-and 0/imm32/false
    16102       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16103       # v = parse-var-with-type(word-slice, first-line)
    16104       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16105       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16106       # assert(var->register != null)
    16107       # . eax: (addr var) = lookup(v)
    16108       (lookup *ebx *(ebx+4))  # => eax
    16109       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16110       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
    16111       # if (var->name != "_") abort
    16112       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16113       (string-equal? %eax "_")  # => eax
    16114       3d/compare-eax-and 0/imm32/false
    16115       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
    16116       # if v->type is an addr, abort
    16117       (lookup *ebx *(ebx+4))  # => eax
    16118       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16119       (mu-addr-type? %eax)  # => eax
    16120       3d/compare-eax-and 0/imm32/false
    16121       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
    16122       # out->outputs = append(v, out->outputs)
    16123       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16124       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16125       #
    16126       e9/jump loop/disp32
    16127     }
    16128 $populate-mu-function-header:done:
    16129     (check-no-tokens-left *(ebp+8))
    16130 $populate-mu-function-header:end:
    16131     # . reclaim locals
    16132     81 0/subop/add %esp 0x10/imm32
    16133     # . restore registers
    16134     5f/pop-to-edi
    16135     5b/pop-to-ebx
    16136     5a/pop-to-edx
    16137     59/pop-to-ecx
    16138     58/pop-to-eax
    16139     # . epilogue
    16140     89/<- %esp 5/r32/ebp
    16141     5d/pop-to-ebp
    16142     c3/return
    16143
    16144 $populate-mu-function-header:error1:
    16145     # error("function header not in form 'fn <name> {'")
    16146     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16147     (flush *(ebp+0x14))
    16148     (rewind-stream *(ebp+8))
    16149     (write-stream-data *(ebp+0x14) *(ebp+8))
    16150     (write-buffered *(ebp+0x14) "'\n")
    16151     (flush *(ebp+0x14))
    16152     (stop *(ebp+0x18) 1)
    16153     # never gets here
    16154
    16155 $populate-mu-function-header:error2:
    16156     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16157     (write-buffered *(ebp+0x14) "fn ")
    16158     50/push-eax
    16159     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16160     (write-buffered *(ebp+0x14) %eax)
    16161     58/pop-to-eax
    16162     (write-buffered *(ebp+0x14) ": function inout '")
    16163     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16164     (write-buffered *(ebp+0x14) %eax)
    16165     (write-buffered *(ebp+0x14) "' cannot be in a register")
    16166     (flush *(ebp+0x14))
    16167     (stop *(ebp+0x18) 1)
    16168     # never gets here
    16169
    16170 $populate-mu-function-header:error3:
    16171     # error("fn " fn ": function output '" var "' must be in a register")
    16172     (write-buffered *(ebp+0x14) "fn ")
    16173     50/push-eax
    16174     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16175     (write-buffered *(ebp+0x14) %eax)
    16176     58/pop-to-eax
    16177     (write-buffered *(ebp+0x14) ": function output '")
    16178     (lookup *ebx *(ebx+4))  # => eax
    16179     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16180     (write-buffered *(ebp+0x14) %eax)
    16181     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
    16182     (rewind-stream *(ebp+8))
    16183     (write-stream-data *(ebp+0x14) *(ebp+8))
    16184     (write-buffered *(ebp+0x14) "'\n")
    16185     (flush *(ebp+0x14))
    16186     (stop *(ebp+0x18) 1)
    16187     # never gets here
    16188
    16189 $populate-mu-function-header:error4:
    16190     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16191     (write-buffered *(ebp+0x14) "fn ")
    16192     50/push-eax
    16193     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16194     (write-buffered *(ebp+0x14) %eax)
    16195     58/pop-to-eax
    16196     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
    16197     (lookup *ebx *(ebx+4))  # => eax
    16198     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16199     (write-buffered *(ebp+0x14) %eax)
    16200     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
    16201     (flush *(ebp+0x14))
    16202     (stop *(ebp+0x18) 1)
    16203     # never gets here
    16204
    16205 $populate-mu-function-header:error-duplicate:
    16206     (write-buffered *(ebp+0x14) "fn ")
    16207     (write-slice-buffered *(ebp+0x14) %ecx)
    16208     (write-buffered *(ebp+0x14) " defined more than once\n")
    16209     (flush *(ebp+0x14))
    16210     (stop *(ebp+0x18) 1)
    16211     # never gets here
    16212
    16213 $populate-mu-function-header:error-break:
    16214     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16215     (flush *(ebp+0x14))
    16216     (stop *(ebp+0x18) 1)
    16217     # never gets here
    16218
    16219 $populate-mu-function-header:error-loop:
    16220     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16221     (flush *(ebp+0x14))
    16222     (stop *(ebp+0x18) 1)
    16223     # never gets here
    16224
    16225 $populate-mu-function-header:error-lookup:
    16226     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
    16227     (flush *(ebp+0x14))
    16228     (stop *(ebp+0x18) 1)
    16229     # never gets here
    16230
    16231 $populate-mu-function-header:error-addr-output:
    16232     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16233     (write-buffered *(ebp+0x14) "fn ")
    16234     50/push-eax
    16235     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16236     (write-buffered *(ebp+0x14) %eax)
    16237     58/pop-to-eax
    16238     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16239     (flush *(ebp+0x14))
    16240     (stop *(ebp+0x18) 1)
    16241     # never gets here
    16242
    16243 $populate-mu-function-header:error-nested-addr-inout:
    16244     # 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")
    16245     (write-buffered *(ebp+0x14) "fn ")
    16246     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16247     (write-buffered *(ebp+0x14) %eax)
    16248     (write-buffered *(ebp+0x14) ": inout '")
    16249     (lookup *ebx *(ebx+4))  # => eax
    16250     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16251     (write-buffered *(ebp+0x14) %eax)
    16252     (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")
    16253     (flush *(ebp+0x14))
    16254     (stop *(ebp+0x18) 1)
    16255     # never gets here
    16256
    16257 # scenarios considered:
    16258 # ✓ fn foo
    16259 # ✗ fn foo {
    16260 # ✓ fn foo x
    16261 # ✓ fn foo x: int
    16262 # ✓ fn foo x: int -> _/eax: int
    16263 # TODO:
    16264 #   disallow outputs of type `(... addr ...)`
    16265 #   disallow inputs of type `(... addr ... addr ...)`
    16266 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    16267     # pseudocode:
    16268     #   var word-slice: slice
    16269     #   next-mu-token(first-line, word-slice)
    16270     #   assert(word-slice not in '{' '}' '->')
    16271     #   out->name = slice-to-string(word-slice)
    16272     #   ## inouts
    16273     #   while true
    16274     #     word-slice = next-mu-token(first-line)
    16275     #     if slice-empty?(word-slice) break
    16276     #     if (word-slice == '->') break
    16277     #     assert(word-slice not in '{' '}')
    16278     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16279     #     assert(v->register == null)
    16280     #     # v->block-depth is implicitly 0
    16281     #     out->inouts = append(v, out->inouts)
    16282     #   ## outputs
    16283     #   while true
    16284     #     word-slice = next-mu-token(first-line)
    16285     #     if slice-empty?(word-slice) break
    16286     #     assert(word-slice not in '{' '}' '->')
    16287     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16288     #     assert(v->register != null)
    16289     #     out->outputs = append(v, out->outputs)
    16290     #
    16291     # . prologue
    16292     55/push-ebp
    16293     89/<- %ebp 4/r32/esp
    16294     # . save registers
    16295     50/push-eax
    16296     51/push-ecx
    16297     52/push-edx
    16298     53/push-ebx
    16299     57/push-edi
    16300     # edi = out
    16301     8b/-> *(ebp+0xc) 7/r32/edi
    16302     # var word-slice/ecx: slice
    16303     68/push 0/imm32/end
    16304     68/push 0/imm32/start
    16305     89/<- %ecx 4/r32/esp
    16306     # var v/ebx: (handle var)
    16307     68/push 0/imm32
    16308     68/push 0/imm32
    16309     89/<- %ebx 4/r32/esp
    16310     # read function name
    16311     (next-mu-token *(ebp+8) %ecx)
    16312     # error checking
    16313     # if (word-slice == '{') abort
    16314     (slice-equal? %ecx "{")   # => eax
    16315     3d/compare-eax-and 0/imm32/false
    16316     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16317     # if (word-slice == '->') abort
    16318     (slice-equal? %ecx "->")   # => eax
    16319     3d/compare-eax-and 0/imm32/false
    16320     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16321     # if (word-slice == '}') abort
    16322     (slice-equal? %ecx "}")   # => eax
    16323     3d/compare-eax-and 0/imm32/false
    16324     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16325     # if word-slice already defined, abort
    16326     (function-exists? %ecx)  # => eax
    16327     3d/compare-eax-and 0/imm32/false
    16328     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
    16329     #
    16330     (slice-starts-with? %ecx "break")  # => eax
    16331     3d/compare-eax-and 0/imm32/false
    16332     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
    16333     (slice-starts-with? %ecx "loop")  # => eax
    16334     3d/compare-eax-and 0/imm32/false
    16335     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
    16336     # save function name
    16337     (slice-to-string Heap %ecx %edi)  # Function-name
    16338     # save function inouts
    16339     {
    16340 $populate-mu-function-signature:check-for-inout:
    16341       (next-mu-token *(ebp+8) %ecx)
    16342       (slice-empty? %ecx)  # => eax
    16343       3d/compare-eax-and 0/imm32/false
    16344       0f 85/jump-if-!= break/disp32
    16345       # if (word-slice == '->') break
    16346       (slice-equal? %ecx "->")   # => eax
    16347       3d/compare-eax-and 0/imm32/false
    16348       0f 85/jump-if-!= break/disp32
    16349       # if (word-slice == '{') abort
    16350       (slice-equal? %ecx "{")   # => eax
    16351       3d/compare-eax-and 0/imm32/false
    16352       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16353       # if (word-slice == '}') abort
    16354       (slice-equal? %ecx "}")   # => eax
    16355       3d/compare-eax-and 0/imm32/false
    16356       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16357       # v = parse-var-with-type(word-slice, first-line)
    16358       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16359       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16360       # if (v->register != null) abort
    16361       # . eax: (addr var) = lookup(v)
    16362       (lookup *ebx *(ebx+4))  # => eax
    16363       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16364       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16365       # if function name is not "main"
    16366       #    and v->type contains an 'addr' anywhere except the start, abort
    16367       {
    16368         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16369         (string-equal? %eax "main")  # => eax
    16370         3d/compare-eax-and 0/imm32/false
    16371         75/jump-if-!= break/disp8
    16372         (lookup *ebx *(ebx+4))  # => eax
    16373         (addr-payload-contains-addr? %eax)  # => eax
    16374         3d/compare-eax-and 0/imm32/false
    16375         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
    16376       }
    16377       # assert(v->register == null)
    16378       # . eax: (addr var) = lookup(v)
    16379       (lookup *ebx *(ebx+4))  # => eax
    16380       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16381       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16382       # v->block-depth is implicitly 0
    16383       #
    16384       # out->inouts = append(v, out->inouts)
    16385       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16386       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16387       #
    16388       e9/jump loop/disp32
    16389     }
    16390     # save function outputs
    16391     {
    16392 $populate-mu-function-signature:check-for-out:
    16393       (next-mu-token *(ebp+8) %ecx)
    16394       (slice-empty? %ecx)  # => eax
    16395       3d/compare-eax-and 0/imm32/false
    16396       0f 85/jump-if-!= break/disp32
    16397       # if (word-slice == '{') abort
    16398       (slice-equal? %ecx "{")   # => eax
    16399       3d/compare-eax-and 0/imm32/false
    16400       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16401       # if (word-slice == '->') abort
    16402       (slice-equal? %ecx "->")   # => eax
    16403       3d/compare-eax-and 0/imm32/false
    16404       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16405       # if (word-slice == '}') abort
    16406       (slice-equal? %ecx "}")   # => eax
    16407       3d/compare-eax-and 0/imm32/false
    16408       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16409       # v = parse-var-with-type(word-slice, first-line)
    16410       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16411       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16412       # assert(var->register != null)
    16413       # . eax: (addr var) = lookup(v)
    16414       (lookup *ebx *(ebx+4))  # => eax
    16415       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16416       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
    16417       # if (var->name != "_") abort
    16418       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16419       (string-equal? %eax "_")  # => eax
    16420       3d/compare-eax-and 0/imm32/false
    16421       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
    16422       # if function name is not "lookup"
    16423       #    and v->type is an addr, abort
    16424       {
    16425         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16426         (string-equal? %eax "lookup")  # => eax
    16427         3d/compare-eax-and 0/imm32/false
    16428         75/jump-if-!= break/disp8
    16429         (lookup *ebx *(ebx+4))  # => eax
    16430         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16431         (mu-addr-type? %eax)  # => eax
    16432         3d/compare-eax-and 0/imm32/false
    16433         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
    16434       }
    16435       # out->outputs = append(v, out->outputs)
    16436       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16437       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16438       #
    16439       e9/jump loop/disp32
    16440     }
    16441 $populate-mu-function-signature:done:
    16442     (check-no-tokens-left *(ebp+8))
    16443 $populate-mu-function-signature:end:
    16444     # . reclaim locals
    16445     81 0/subop/add %esp 0x10/imm32
    16446     # . restore registers
    16447     5f/pop-to-edi
    16448     5b/pop-to-ebx
    16449     5a/pop-to-edx
    16450     59/pop-to-ecx
    16451     58/pop-to-eax
    16452     # . epilogue
    16453     89/<- %esp 5/r32/ebp
    16454     5d/pop-to-ebp
    16455     c3/return
    16456
    16457 $populate-mu-function-signature:error1:
    16458     # error("function signature not in form 'fn <name> {'")
    16459     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16460     (flush *(ebp+0x10))
    16461     (rewind-stream *(ebp+8))
    16462     (write-stream-data *(ebp+0x10) *(ebp+8))
    16463     (write-buffered *(ebp+0x10) "'\n")
    16464     (flush *(ebp+0x10))
    16465     (stop *(ebp+0x14) 1)
    16466     # never gets here
    16467
    16468 $populate-mu-function-signature:error2:
    16469     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16470     (write-buffered *(ebp+0x10) "fn ")
    16471     50/push-eax
    16472     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16473     (write-buffered *(ebp+0x10) %eax)
    16474     58/pop-to-eax
    16475     (write-buffered *(ebp+0x10) ": function inout '")
    16476     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16477     (write-buffered *(ebp+0x10) %eax)
    16478     (write-buffered *(ebp+0x10) "' cannot be in a register")
    16479     (flush *(ebp+0x10))
    16480     (stop *(ebp+0x14) 1)
    16481     # never gets here
    16482
    16483 $populate-mu-function-signature:error3:
    16484     # error("fn " fn ": function output '" var "' must be in a register")
    16485     (write-buffered *(ebp+0x10) "fn ")
    16486     50/push-eax
    16487     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16488     (write-buffered *(ebp+0x10) %eax)
    16489     58/pop-to-eax
    16490     (write-buffered *(ebp+0x10) ": function output '")
    16491     (lookup *ebx *(ebx+4))  # => eax
    16492     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16493     (write-buffered *(ebp+0x10) %eax)
    16494     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
    16495     (rewind-stream *(ebp+8))
    16496     (write-stream-data *(ebp+0x10) *(ebp+8))
    16497     (write-buffered *(ebp+0x10) "'\n")
    16498     (flush *(ebp+0x10))
    16499     (stop *(ebp+0x14) 1)
    16500     # never gets here
    16501
    16502 $populate-mu-function-signature:error4:
    16503     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16504     (write-buffered *(ebp+0x10) "fn ")
    16505     50/push-eax
    16506     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16507     (write-buffered *(ebp+0x10) %eax)
    16508     58/pop-to-eax
    16509     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
    16510     (lookup *ebx *(ebx+4))  # => eax
    16511     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16512     (write-buffered *(ebp+0x10) %eax)
    16513     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
    16514     (flush *(ebp+0x10))
    16515     (stop *(ebp+0x14) 1)
    16516     # never gets here
    16517
    16518 $populate-mu-function-signature:error-duplicate:
    16519     (write-buffered *(ebp+0x10) "fn ")
    16520     (write-slice-buffered *(ebp+0x10) %ecx)
    16521     (write-buffered *(ebp+0x10) " defined more than once\n")
    16522     (flush *(ebp+0x10))
    16523     (stop *(ebp+0x14) 1)
    16524     # never gets here
    16525
    16526 $populate-mu-function-signature:error-break:
    16527     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16528     (flush *(ebp+0x10))
    16529     (stop *(ebp+0x14) 1)
    16530     # never gets here
    16531
    16532 $populate-mu-function-signature:error-loop:
    16533     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16534     (flush *(ebp+0x10))
    16535     (stop *(ebp+0x14) 1)
    16536     # never gets here
    16537
    16538 $populate-mu-function-signature:error-addr-output:
    16539     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16540     (write-buffered *(ebp+0x10) "fn ")
    16541     50/push-eax
    16542     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16543     (write-buffered *(ebp+0x10) %eax)
    16544     58/pop-to-eax
    16545     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16546     (flush *(ebp+0x10))
    16547     (stop *(ebp+0x14) 1)
    16548     # never gets here
    16549
    16550 $populate-mu-function-signature:error-nested-addr-inout:
    16551     # 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")
    16552     (write-buffered *(ebp+0x10) "fn ")
    16553     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16554     (write-buffered *(ebp+0x10) %eax)
    16555     (write-buffered *(ebp+0x10) ": inout '")
    16556     (lookup *ebx *(ebx+4))  # => eax
    16557     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16558     (write-buffered *(ebp+0x10) %eax)
    16559     (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")
    16560     (flush *(ebp+0x10))
    16561     (stop *(ebp+0x14) 1)
    16562     # never gets here
    16563
    16564 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
    16565     # . prologue
    16566     55/push-ebp
    16567     89/<- %ebp 4/r32/esp
    16568     # var t/eax: (addr type-tree) = v->type
    16569     8b/-> *(ebp+8) 0/r32/eax
    16570     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16571     # if t->right contains addr, return true
    16572     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16573     (type-tree-contains? %eax 2)  # addr => eax
    16574     # we don't have to look at t->left as long as it's guaranteed to be an atom
    16575 $addr-payload-contains-addr?:end:
    16576     # . epilogue
    16577     89/<- %esp 5/r32/ebp
    16578     5d/pop-to-ebp
    16579     c3/return
    16580
    16581 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
    16582     # . prologue
    16583     55/push-ebp
    16584     89/<- %ebp 4/r32/esp
    16585     # . save registers
    16586     51/push-ecx
    16587     # if t is null, return false
    16588     8b/-> *(ebp+8) 0/r32/eax
    16589     3d/compare-eax-and 0/imm32
    16590     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
    16591     # if t is an atom, return (t->value == n)
    16592     81 7/subop/compare *eax 0/imm32/false
    16593     {
    16594       74/jump-if-= break/disp8
    16595       8b/-> *(ebp+0xc) 1/r32/ecx
    16596       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    16597       0f 94/set-if-= %al
    16598       81 4/subop/and %eax 0xff/imm32
    16599       eb/jump $type-tree-contains?:end/disp8
    16600     }
    16601     # if t->left contains n, return true
    16602     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    16603     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16604     3d/compare-eax-and 0/imm32/false
    16605     75/jump-if-!= $type-tree-contains?:end/disp8
    16606     # otherwise return whether t->right contains n
    16607     8b/-> *(ebp+8) 0/r32/eax
    16608     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16609     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16610 $type-tree-contains?:end:
    16611     # . restore registers
    16612     59/pop-to-ecx
    16613     # . epilogue
    16614     89/<- %esp 5/r32/ebp
    16615     5d/pop-to-ebp
    16616     c3/return
    16617
    16618 function-exists?:  # s: (addr slice) -> result/eax: boolean
    16619     # . prologue
    16620     55/push-ebp
    16621     89/<- %ebp 4/r32/esp
    16622     # . save registers
    16623     51/push-ecx
    16624     # var curr/ecx: (addr function) = functions
    16625     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    16626     89/<- %ecx 0/r32/eax
    16627     {
    16628       # if (curr == null) break
    16629       81 7/subop/compare %ecx 0/imm32
    16630       74/jump-if-= break/disp8
    16631       # if (curr->name == s) return true
    16632       {
    16633         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16634         (slice-equal? *(ebp+8) %eax)  # => eax
    16635         3d/compare-eax-and 0/imm32/false
    16636         74/jump-if-= break/disp8
    16637         b8/copy-to-eax 1/imm32/true
    16638         e9/jump $function-exists?:end/disp32
    16639       }
    16640       # curr = curr->next
    16641       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16642       89/<- %ecx 0/r32/eax
    16643       #
    16644       eb/jump loop/disp8
    16645     }
    16646     # var curr/ecx: (addr function) = signatures
    16647     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    16648     89/<- %ecx 0/r32/eax
    16649     {
    16650       # if (curr == null) break
    16651       81 7/subop/compare %ecx 0/imm32
    16652       74/jump-if-= break/disp8
    16653       # if (curr->name == s) return true
    16654       {
    16655         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16656         (slice-equal? *(ebp+8) %eax)  # => eax
    16657         3d/compare-eax-and 0/imm32/false
    16658         74/jump-if-= break/disp8
    16659         b8/copy-to-eax 1/imm32/true
    16660         eb/jump $function-exists?:end/disp8
    16661       }
    16662       # curr = curr->next
    16663       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16664       89/<- %ecx 0/r32/eax
    16665       #
    16666       eb/jump loop/disp8
    16667     }
    16668     # return false
    16669     b8/copy-to-eax 0/imm32/false
    16670 $function-exists?:end:
    16671     # . restore registers
    16672     59/pop-to-ecx
    16673     # . epilogue
    16674     89/<- %esp 5/r32/ebp
    16675     5d/pop-to-ebp
    16676     c3/return
    16677
    16678 test-function-header-with-arg:
    16679     # . prologue
    16680     55/push-ebp
    16681     89/<- %ebp 4/r32/esp
    16682     # setup
    16683     8b/-> *Primitive-type-ids 0/r32/eax
    16684     89/<- *Type-id 0/r32/eax  # stream-write
    16685     c7 0/subop/copy *_Program-functions 0/imm32
    16686     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16687     c7 0/subop/copy *_Program-types 0/imm32
    16688     c7 0/subop/copy *_Program-types->payload 0/imm32
    16689     c7 0/subop/copy *_Program-signatures 0/imm32
    16690     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16691     (clear-stream _test-input-stream)
    16692     (write _test-input-stream "foo n: int {\n")
    16693     # var result/ecx: function
    16694     2b/subtract *Function-size 4/r32/esp
    16695     89/<- %ecx 4/r32/esp
    16696     (zero-out %ecx *Function-size)
    16697     # var vars/ebx: (stack live-var 16)
    16698     81 5/subop/subtract %esp 0xc0/imm32
    16699     68/push 0xc0/imm32/size
    16700     68/push 0/imm32/top
    16701     89/<- %ebx 4/r32/esp
    16702     # convert
    16703     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16704     # check result->name
    16705     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16706     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
    16707     # var v/edx: (addr var) = result->inouts->value
    16708     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16709     (lookup *eax *(eax+4))  # List-value List-value => eax
    16710     89/<- %edx 0/r32/eax
    16711     # check v->name
    16712     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    16713     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
    16714     # check v->type
    16715     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    16716     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
    16717     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
    16718     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
    16719     # . epilogue
    16720     89/<- %esp 5/r32/ebp
    16721     5d/pop-to-ebp
    16722     c3/return
    16723
    16724 test-function-header-with-multiple-args:
    16725     # . prologue
    16726     55/push-ebp
    16727     89/<- %ebp 4/r32/esp
    16728     # setup
    16729     8b/-> *Primitive-type-ids 0/r32/eax
    16730     89/<- *Type-id 0/r32/eax  # stream-write
    16731     c7 0/subop/copy *_Program-functions 0/imm32
    16732     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16733     c7 0/subop/copy *_Program-types 0/imm32
    16734     c7 0/subop/copy *_Program-types->payload 0/imm32
    16735     c7 0/subop/copy *_Program-signatures 0/imm32
    16736     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16737     (clear-stream _test-input-stream)
    16738     (write _test-input-stream "foo a: int, b: int c: int {\n")
    16739     # result/ecx: function
    16740     2b/subtract *Function-size 4/r32/esp
    16741     89/<- %ecx 4/r32/esp
    16742     (zero-out %ecx *Function-size)
    16743     # var vars/ebx: (stack live-var 16)
    16744     81 5/subop/subtract %esp 0xc0/imm32
    16745     68/push 0xc0/imm32/size
    16746     68/push 0/imm32/top
    16747     89/<- %ebx 4/r32/esp
    16748     # convert
    16749     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16750     # check result->name
    16751     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16752     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
    16753     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16754     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16755     89/<- %edx 0/r32/eax
    16756 $test-function-header-with-multiple-args:inout0:
    16757     # var v/ebx: (addr var) = lookup(inouts->value)
    16758     (lookup *edx *(edx+4))  # List-value List-value => eax
    16759     89/<- %ebx 0/r32/eax
    16760     # check v->name
    16761     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16762     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
    16763     # check v->type
    16764     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16765     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
    16766     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
    16767     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
    16768 $test-function-header-with-multiple-args:inout1:
    16769     # inouts = lookup(inouts->next)
    16770     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16771     89/<- %edx 0/r32/eax
    16772     # v = lookup(inouts->value)
    16773     (lookup *edx *(edx+4))  # List-value List-value => eax
    16774     89/<- %ebx 0/r32/eax
    16775     # check v->name
    16776     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16777     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
    16778     # check v->type
    16779     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16780     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
    16781     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
    16782     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
    16783 $test-function-header-with-multiple-args:inout2:
    16784     # inouts = lookup(inouts->next)
    16785     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16786     89/<- %edx 0/r32/eax
    16787     # v = lookup(inouts->value)
    16788     (lookup *edx *(edx+4))  # List-value List-value => eax
    16789     89/<- %ebx 0/r32/eax
    16790     # check v->name
    16791     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16792     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
    16793     # check v->type
    16794     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16795     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
    16796     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
    16797     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
    16798     # . epilogue
    16799     89/<- %esp 5/r32/ebp
    16800     5d/pop-to-ebp
    16801     c3/return
    16802
    16803 test-function-header-with-multiple-args-and-outputs:
    16804     # . prologue
    16805     55/push-ebp
    16806     89/<- %ebp 4/r32/esp
    16807     # setup
    16808     8b/-> *Primitive-type-ids 0/r32/eax
    16809     89/<- *Type-id 0/r32/eax  # stream-write
    16810     c7 0/subop/copy *_Program-functions 0/imm32
    16811     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16812     c7 0/subop/copy *_Program-types 0/imm32
    16813     c7 0/subop/copy *_Program-types->payload 0/imm32
    16814     c7 0/subop/copy *_Program-signatures 0/imm32
    16815     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16816     (clear-stream _test-input-stream)
    16817     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
    16818     # result/ecx: function
    16819     2b/subtract *Function-size 4/r32/esp
    16820     89/<- %ecx 4/r32/esp
    16821     (zero-out %ecx *Function-size)
    16822     # var vars/ebx: (stack live-var 16)
    16823     81 5/subop/subtract %esp 0xc0/imm32
    16824     68/push 0xc0/imm32/size
    16825     68/push 0/imm32/top
    16826     89/<- %ebx 4/r32/esp
    16827     # convert
    16828     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16829     # check result->name
    16830     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16831     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
    16832     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16833     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16834     89/<- %edx 0/r32/eax
    16835 $test-function-header-with-multiple-args-and-outputs:inout0:
    16836     # var v/ebx: (addr var) = lookup(inouts->value)
    16837     (lookup *edx *(edx+4))  # List-value List-value => eax
    16838     89/<- %ebx 0/r32/eax
    16839     # check v->name
    16840     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16841     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
    16842     # check v->type
    16843     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16844     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
    16845     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
    16846     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
    16847 $test-function-header-with-multiple-args-and-outputs:inout1:
    16848     # inouts = lookup(inouts->next)
    16849     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16850     89/<- %edx 0/r32/eax
    16851     # v = lookup(inouts->value)
    16852     (lookup *edx *(edx+4))  # List-value List-value => eax
    16853     89/<- %ebx 0/r32/eax
    16854     # check v->name
    16855     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16856     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
    16857     # check v->type
    16858     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16859     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
    16860     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
    16861     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
    16862 $test-function-header-with-multiple-args-and-outputs:inout2:
    16863     # inouts = lookup(inouts->next)
    16864     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16865     89/<- %edx 0/r32/eax
    16866     # v = lookup(inouts->value)
    16867     (lookup *edx *(edx+4))  # List-value List-value => eax
    16868     89/<- %ebx 0/r32/eax
    16869     # check v->name
    16870     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16871     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
    16872     # check v->type
    16873     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16874     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
    16875     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
    16876     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
    16877 $test-function-header-with-multiple-args-and-outputs:out0:
    16878     # var outputs/edx: (addr list var) = lookup(result->outputs)
    16879     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    16880     89/<- %edx 0/r32/eax
    16881     # v = lookup(outputs->value)
    16882     (lookup *edx *(edx+4))  # List-value List-value => eax
    16883     89/<- %ebx 0/r32/eax
    16884     # check v->name
    16885     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16886     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
    16887     # check v->register
    16888     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16889     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
    16890     # check v->type
    16891     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16892     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
    16893     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
    16894     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
    16895 $test-function-header-with-multiple-args-and-outputs:out1:
    16896     # outputs = lookup(outputs->next)
    16897     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16898     89/<- %edx 0/r32/eax
    16899     # v = lookup(inouts->value)
    16900     (lookup *edx *(edx+4))  # List-value List-value => eax
    16901     89/<- %ebx 0/r32/eax
    16902     # check v->name
    16903     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16904     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
    16905     # check v->register
    16906     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16907     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
    16908     # check v->type
    16909     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16910     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
    16911     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
    16912     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
    16913     # . epilogue
    16914     89/<- %esp 5/r32/ebp
    16915     5d/pop-to-ebp
    16916     c3/return
    16917
    16918 # format for variables with types
    16919 #   x: int
    16920 #   x: int,
    16921 #   x/eax: int
    16922 #   x/eax: int,
    16923 # ignores at most one trailing comma
    16924 # does not support other, non-register metadata
    16925 # WARNING: modifies name
    16926 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)
    16927     # pseudocode:
    16928     #   var s: slice
    16929     #   if (!slice-ends-with(name, ":"))
    16930     #     abort
    16931     #   --name->end to skip ':'
    16932     #   next-token-from-slice(name->start, name->end, '/', s)
    16933     #   new-var-from-slice(s, out)
    16934     #   ## register
    16935     #   next-token-from-slice(s->end, name->end, '/', s)
    16936     #   if (!slice-empty?(s))
    16937     #     out->register = slice-to-string(s)
    16938     #   ## type
    16939     #   var type: (handle type-tree) = parse-type(first-line)
    16940     #   out->type = type
    16941     #
    16942     # . prologue
    16943     55/push-ebp
    16944     89/<- %ebp 4/r32/esp
    16945     # . save registers
    16946     50/push-eax
    16947     51/push-ecx
    16948     52/push-edx
    16949     53/push-ebx
    16950     56/push-esi
    16951     57/push-edi
    16952     # esi = name
    16953     8b/-> *(ebp+8) 6/r32/esi
    16954     # if (!slice-ends-with?(name, ":")) abort
    16955     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
    16956     49/decrement-ecx
    16957     8a/copy-byte *ecx 1/r32/CL
    16958     81 4/subop/and %ecx 0xff/imm32
    16959     81 7/subop/compare %ecx 0x3a/imm32/colon
    16960     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
    16961     # --name->end to skip ':'
    16962     ff 1/subop/decrement *(esi+4)
    16963     # var s/ecx: slice
    16964     68/push 0/imm32/end
    16965     68/push 0/imm32/start
    16966     89/<- %ecx 4/r32/esp
    16967 $parse-var-with-type:parse-name:
    16968     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
    16969 $parse-var-with-type:create-var:
    16970     # new-var-from-slice(s, out)
    16971     (new-var-from-slice Heap %ecx *(ebp+0x10))
    16972     # save out->register
    16973 $parse-var-with-type:save-register:
    16974     # . var out-addr/edi: (addr var) = lookup(*out)
    16975     8b/-> *(ebp+0x10) 7/r32/edi
    16976     (lookup *edi *(edi+4))  # => eax
    16977     89/<- %edi 0/r32/eax
    16978     # . s = next-token(...)
    16979     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
    16980     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
    16981     {
    16982 $parse-var-with-type:write-register:
    16983       (slice-empty? %ecx)  # => eax
    16984       3d/compare-eax-and 0/imm32/false
    16985       75/jump-if-!= break/disp8
    16986       # out->register = slice-to-string(s)
    16987       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
    16988       (slice-to-string Heap %ecx %eax)
    16989     }
    16990 $parse-var-with-type:save-type:
    16991     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
    16992     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
    16993 $parse-var-with-type:check-register:
    16994     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    16995     3d/compare-eax-and 0/imm32
    16996     74/jump-if-= $parse-var-with-type:end/disp8
    16997     (float-register? %eax)  # => eax
    16998     {
    16999       3d/compare-eax-and 0/imm32/false
    17000       74/jump-if-= break/disp8
    17001       # var is in a float register; ensure type is float
    17002       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17003       (simple-mu-type? %eax 0xf)  # float => eax
    17004       3d/compare-eax-and 0/imm32/false
    17005       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
    17006       eb/jump $parse-var-with-type:end/disp8
    17007     }
    17008     # var is not in a float register; ensure type is not float
    17009     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17010     (simple-mu-type? %eax 0xf)  # float => eax
    17011     3d/compare-eax-and 0/imm32/false
    17012     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
    17013 $parse-var-with-type:end:
    17014     # . reclaim locals
    17015     81 0/subop/add %esp 8/imm32
    17016     # . restore registers
    17017     5f/pop-to-edi
    17018     5e/pop-to-esi
    17019     5b/pop-to-ebx
    17020     5a/pop-to-edx
    17021     59/pop-to-ecx
    17022     58/pop-to-eax
    17023     # . epilogue
    17024     89/<- %esp 5/r32/ebp
    17025     5d/pop-to-ebp
    17026     c3/return
    17027
    17028 $parse-var-with-type:abort:
    17029     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
    17030     (write-buffered *(ebp+0x18) "fn ")
    17031     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17032     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
    17033     (flush *(ebp+0x18))
    17034     (rewind-stream *(ebp+0xc))
    17035     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    17036     (write-buffered *(ebp+0x18) "'\n")
    17037     (flush *(ebp+0x18))
    17038     (stop *(ebp+0x1c) 1)
    17039     # never gets here
    17040
    17041 $parse-var-with-type:error-float-in-integer-register:
    17042     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
    17043     (write-buffered *(ebp+0x18) "fn ")
    17044     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17045     (write-buffered *(ebp+0x18) ": float var '")
    17046     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17047     (write-buffered *(ebp+0x18) %eax)
    17048     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
    17049     (flush *(ebp+0x18))
    17050     (stop *(ebp+0x1c) 1)
    17051     # never gets here
    17052
    17053 $parse-var-with-type:error-non-float-in-floating-point-register:
    17054     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
    17055     (write-buffered *(ebp+0x18) "fn ")
    17056     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17057     (write-buffered *(ebp+0x18) ": non-float var '")
    17058     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17059     (write-buffered *(ebp+0x18) %eax)
    17060     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
    17061     (flush *(ebp+0x18))
    17062     (stop *(ebp+0x1c) 1)
    17063     # never gets here
    17064
    17065 float-register?:  # r: (addr array byte) -> result/eax: boolean
    17066     # . prologue
    17067     55/push-ebp
    17068     89/<- %ebp 4/r32/esp
    17069     #
    17070     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
    17071     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
    17072     0f 9d/set-if->= %al
    17073     81 4/subop/and %eax 0xff/imm32
    17074 $float-register?:end:
    17075     # . epilogue
    17076     89/<- %esp 5/r32/ebp
    17077     5d/pop-to-ebp
    17078     c3/return
    17079
    17080 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17081     # pseudocode:
    17082     #   var s: slice = next-mu-token(in)
    17083     #   assert s != ""
    17084     #   assert s != "->"
    17085     #   assert s != "{"
    17086     #   assert s != "}"
    17087     #   if s == ")"
    17088     #     return
    17089     #   out = allocate(Type-tree)
    17090     #   if s != "("
    17091     #     HACK: if s is an int, parse and return it
    17092     #     out->is-atom? = true
    17093     #     if (s[0] == "_")
    17094     #       out->value = type-parameter
    17095     #       out->parameter-name = slice-to-string(ad, s)
    17096     #     else
    17097     #       out->value = pos-or-insert-slice(Type-id, s)
    17098     #     return
    17099     #   out->left = parse-type(ad, in)
    17100     #   out->right = parse-type-tree(ad, in)
    17101     #
    17102     # . prologue
    17103     55/push-ebp
    17104     89/<- %ebp 4/r32/esp
    17105     # . save registers
    17106     50/push-eax
    17107     51/push-ecx
    17108     52/push-edx
    17109     # clear out
    17110     (zero-out *(ebp+0x10) *Handle-size)
    17111     # var s/ecx: slice
    17112     68/push 0/imm32
    17113     68/push 0/imm32
    17114     89/<- %ecx 4/r32/esp
    17115     # s = next-mu-token(in)
    17116     (next-mu-token *(ebp+0xc) %ecx)
    17117 #?     (write-buffered Stderr "tok: ")
    17118 #?     (write-slice-buffered Stderr %ecx)
    17119 #?     (write-buffered Stderr "$\n")
    17120 #?     (flush Stderr)
    17121     # assert s != ""
    17122     (slice-equal? %ecx "")  # => eax
    17123     3d/compare-eax-and 0/imm32/false
    17124     0f 85/jump-if-!= $parse-type:abort/disp32
    17125     # assert s != "{"
    17126     (slice-equal? %ecx "{")  # => eax
    17127     3d/compare-eax-and 0/imm32/false
    17128     0f 85/jump-if-!= $parse-type:abort/disp32
    17129     # assert s != "}"
    17130     (slice-equal? %ecx "}")  # => eax
    17131     3d/compare-eax-and 0/imm32/false
    17132     0f 85/jump-if-!= $parse-type:abort/disp32
    17133     # assert s != "->"
    17134     (slice-equal? %ecx "->")  # => eax
    17135     3d/compare-eax-and 0/imm32/false
    17136     0f 85/jump-if-!= $parse-type:abort/disp32
    17137     # if (s == ")") return
    17138     (slice-equal? %ecx ")")  # => eax
    17139     3d/compare-eax-and 0/imm32/false
    17140     0f 85/jump-if-!= $parse-type:end/disp32
    17141     # out = new tree
    17142     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17143     # var out-addr/edx: (addr type-tree) = lookup(*out)
    17144     8b/-> *(ebp+0x10) 2/r32/edx
    17145     (lookup *edx *(edx+4))  # => eax
    17146     89/<- %edx 0/r32/eax
    17147     {
    17148       # if (s != "(") break
    17149       (slice-equal? %ecx "(")  # => eax
    17150       3d/compare-eax-and 0/imm32/false
    17151       0f 85/jump-if-!= break/disp32
    17152       # if s is a number, store it in the type's size field
    17153       {
    17154 $parse-type:check-for-int:
    17155         # var tmp/eax: byte = *s->slice
    17156         8b/-> *ecx 0/r32/eax
    17157         8a/copy-byte *eax 0/r32/AL
    17158         81 4/subop/and %eax 0xff/imm32
    17159         # TODO: raise an error on `var x: (array int a)`
    17160         (decimal-digit? %eax)  # => eax
    17161         3d/compare-eax-and 0/imm32/false
    17162         74/jump-if-= break/disp8
    17163 $parse-type:int:
    17164         # strip out metadata
    17165         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
    17166         #
    17167         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
    17168         (parse-hex-int-from-slice %ecx)  # => eax
    17169         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
    17170         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
    17171         e9/jump $parse-type:end/disp32
    17172       }
    17173 $parse-type:atom:
    17174       # out->is-atom? = true
    17175       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
    17176       {
    17177 $parse-type:check-for-type-parameter:
    17178         # var tmp/eax: byte = *s->slice
    17179         8b/-> *ecx 0/r32/eax
    17180         8a/copy-byte *eax 0/r32/AL
    17181         81 4/subop/and %eax 0xff/imm32
    17182         # if (tmp != '_') break
    17183         3d/compare-eax-and 0x5f/imm32/_
    17184         75/jump-if-!= break/disp8
    17185 $parse-type:type-parameter:
    17186         # out->value = type-parameter
    17187         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
    17188         # out->parameter-name = slice-to-string(ad, s)
    17189         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
    17190         (slice-to-string *(ebp+8) %ecx %eax)
    17191         e9/jump $parse-type:end/disp32
    17192       }
    17193 $parse-type:non-type-parameter:
    17194       # out->value = pos-or-insert-slice(Type-id, s)
    17195       (pos-or-insert-slice Type-id %ecx)  # => eax
    17196       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
    17197       e9/jump $parse-type:end/disp32
    17198     }
    17199 $parse-type:non-atom:
    17200     # otherwise s == "("
    17201     # out->left = parse-type(ad, in)
    17202     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
    17203     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17204     # out->right = parse-type-tree(ad, in)
    17205     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17206     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17207 $parse-type:end:
    17208     # . reclaim locals
    17209     81 0/subop/add %esp 8/imm32
    17210     # . restore registers
    17211     5a/pop-to-edx
    17212     59/pop-to-ecx
    17213     58/pop-to-eax
    17214     # . epilogue
    17215     89/<- %esp 5/r32/ebp
    17216     5d/pop-to-ebp
    17217     c3/return
    17218
    17219 $parse-type:abort:
    17220     # error("unexpected token when parsing type: '" s "'\n")
    17221     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
    17222     (write-slice-buffered *(ebp+0x14) %ecx)
    17223     (write-buffered *(ebp+0x14) "'\n")
    17224     (flush *(ebp+0x14))
    17225     (stop *(ebp+0x18) 1)
    17226     # never gets here
    17227
    17228 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17229     # pseudocode:
    17230     #   var tmp: (handle type-tree) = parse-type(ad, in)
    17231     #   if tmp == 0
    17232     #     return 0
    17233     #   out = allocate(Type-tree)
    17234     #   out->left = tmp
    17235     #   out->right = parse-type-tree(ad, in)
    17236     #
    17237     # . prologue
    17238     55/push-ebp
    17239     89/<- %ebp 4/r32/esp
    17240     # . save registers
    17241     50/push-eax
    17242     51/push-ecx
    17243     52/push-edx
    17244     #
    17245     (zero-out *(ebp+0x10) *Handle-size)
    17246     # var tmp/ecx: (handle type-tree)
    17247     68/push 0/imm32
    17248     68/push 0/imm32
    17249     89/<- %ecx 4/r32/esp
    17250     # tmp = parse-type(ad, in)
    17251     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
    17252     # if (tmp == 0) return
    17253     81 7/subop/compare *ecx 0/imm32
    17254     74/jump-if-= $parse-type-tree:end/disp8
    17255     # out = new tree
    17256     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17257     # var out-addr/edx: (addr tree) = lookup(*out)
    17258     8b/-> *(ebp+0x10) 2/r32/edx
    17259     (lookup *edx *(edx+4))  # => eax
    17260     89/<- %edx 0/r32/eax
    17261     # out->left = tmp
    17262     8b/-> *ecx 0/r32/eax
    17263     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
    17264     8b/-> *(ecx+4) 0/r32/eax
    17265     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
    17266     # out->right = parse-type-tree(ad, in)
    17267     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17268     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17269 $parse-type-tree:end:
    17270     # . reclaim locals
    17271     81 0/subop/add %esp 8/imm32
    17272     # . restore registers
    17273     5a/pop-to-edx
    17274     59/pop-to-ecx
    17275     58/pop-to-eax
    17276     # . epilogue
    17277     89/<- %esp 5/r32/ebp
    17278     5d/pop-to-ebp
    17279     c3/return
    17280
    17281 next-mu-token:  # in: (addr stream byte), out: (addr slice)
    17282     # pseudocode:
    17283     # start:
    17284     #   skip-chars-matching-whitespace(in)
    17285     #   if in->read >= in->write              # end of in
    17286     #     out = {0, 0}
    17287     #     return
    17288     #   out->start = &in->data[in->read]
    17289     #   var curr-byte/eax: byte = in->data[in->read]
    17290     #   if curr->byte == ','                  # comment token
    17291     #     ++in->read
    17292     #     goto start
    17293     #   if curr-byte == '#'                   # comment
    17294     #     goto done                             # treat as eof
    17295     #   if curr-byte == '"'                   # string literal
    17296     #     skip-string(in)
    17297     #     goto done                           # no metadata
    17298     #   if curr-byte == '('
    17299     #     ++in->read
    17300     #     goto done
    17301     #   if curr-byte == ')'
    17302     #     ++in->read
    17303     #     goto done
    17304     #   # read a word
    17305     #   while true
    17306     #     if in->read >= in->write
    17307     #       break
    17308     #     curr-byte = in->data[in->read]
    17309     #     if curr-byte == ' '
    17310     #       break
    17311     #     if curr-byte == '\r'
    17312     #       break
    17313     #     if curr-byte == '\n'
    17314     #       break
    17315     #     if curr-byte == '('
    17316     #       break
    17317     #     if curr-byte == ')'
    17318     #       break
    17319     #     if curr-byte == ','
    17320     #       break
    17321     #     ++in->read
    17322     # done:
    17323     #   out->end = &in->data[in->read]
    17324     #
    17325     # . prologue
    17326     55/push-ebp
    17327     89/<- %ebp 4/r32/esp
    17328     # . save registers
    17329     50/push-eax
    17330     51/push-ecx
    17331     56/push-esi
    17332     57/push-edi
    17333     # esi = in
    17334     8b/-> *(ebp+8) 6/r32/esi
    17335     # edi = out
    17336     8b/-> *(ebp+0xc) 7/r32/edi
    17337 $next-mu-token:start:
    17338     (skip-chars-matching-whitespace %esi)
    17339 $next-mu-token:check0:
    17340     # if (in->read >= in->write) return out = {0, 0}
    17341     # . ecx = in->read
    17342     8b/-> *(esi+4) 1/r32/ecx
    17343     # . if (ecx >= in->write) return out = {0, 0}
    17344     3b/compare<- *esi 1/r32/ecx
    17345     c7 0/subop/copy *edi 0/imm32
    17346     c7 0/subop/copy *(edi+4) 0/imm32
    17347     0f 8d/jump-if->= $next-mu-token:end/disp32
    17348     # out->start = &in->data[in->read]
    17349     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17350     89/<- *edi 0/r32/eax
    17351     # var curr-byte/eax: byte = in->data[in->read]
    17352     31/xor-with %eax 0/r32/eax
    17353     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17354     {
    17355 $next-mu-token:check-for-comma:
    17356       # if (curr-byte != ',') break
    17357       3d/compare-eax-and 0x2c/imm32/comma
    17358       75/jump-if-!= break/disp8
    17359       # ++in->read
    17360       ff 0/subop/increment *(esi+4)
    17361       # restart
    17362       e9/jump $next-mu-token:start/disp32
    17363     }
    17364     {
    17365 $next-mu-token:check-for-comment:
    17366       # if (curr-byte != '#') break
    17367       3d/compare-eax-and 0x23/imm32/pound
    17368       75/jump-if-!= break/disp8
    17369       # return eof
    17370       e9/jump $next-mu-token:done/disp32
    17371     }
    17372     {
    17373 $next-mu-token:check-for-string-literal:
    17374       # if (curr-byte != '"') break
    17375       3d/compare-eax-and 0x22/imm32/dquote
    17376       75/jump-if-!= break/disp8
    17377       (skip-string %esi)
    17378       # return
    17379       e9/jump $next-mu-token:done/disp32
    17380     }
    17381     {
    17382 $next-mu-token:check-for-open-paren:
    17383       # if (curr-byte != '(') break
    17384       3d/compare-eax-and 0x28/imm32/open-paren
    17385       75/jump-if-!= break/disp8
    17386       # ++in->read
    17387       ff 0/subop/increment *(esi+4)
    17388       # return
    17389       e9/jump $next-mu-token:done/disp32
    17390     }
    17391     {
    17392 $next-mu-token:check-for-close-paren:
    17393       # if (curr-byte != ')') break
    17394       3d/compare-eax-and 0x29/imm32/close-paren
    17395       75/jump-if-!= break/disp8
    17396       # ++in->read
    17397       ff 0/subop/increment *(esi+4)
    17398       # return
    17399       e9/jump $next-mu-token:done/disp32
    17400     }
    17401     {
    17402 $next-mu-token:regular-word-without-metadata:
    17403       # if (in->read >= in->write) break
    17404       # . ecx = in->read
    17405       8b/-> *(esi+4) 1/r32/ecx
    17406       # . if (ecx >= in->write) break
    17407       3b/compare<- *esi 1/r32/ecx
    17408       7d/jump-if->= break/disp8
    17409       # var c/eax: byte = in->data[in->read]
    17410       31/xor-with %eax 0/r32/eax
    17411       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17412       # if (c == ' ') break
    17413       3d/compare-eax-and 0x20/imm32/space
    17414       74/jump-if-= break/disp8
    17415       # if (c == '\r') break
    17416       3d/compare-eax-and 0xd/imm32/carriage-return
    17417       74/jump-if-= break/disp8
    17418       # if (c == '\n') break
    17419       3d/compare-eax-and 0xa/imm32/newline
    17420       74/jump-if-= break/disp8
    17421       # if (c == '(') break
    17422       3d/compare-eax-and 0x28/imm32/open-paren
    17423       0f 84/jump-if-= break/disp32
    17424       # if (c == ')') break
    17425       3d/compare-eax-and 0x29/imm32/close-paren
    17426       0f 84/jump-if-= break/disp32
    17427       # if (c == ',') break
    17428       3d/compare-eax-and 0x2c/imm32/comma
    17429       0f 84/jump-if-= break/disp32
    17430       # ++in->read
    17431       ff 0/subop/increment *(esi+4)
    17432       #
    17433       e9/jump loop/disp32
    17434     }
    17435 $next-mu-token:done:
    17436     # out->end = &in->data[in->read]
    17437     8b/-> *(esi+4) 1/r32/ecx
    17438     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17439     89/<- *(edi+4) 0/r32/eax
    17440 $next-mu-token:end:
    17441     # . restore registers
    17442     5f/pop-to-edi
    17443     5e/pop-to-esi
    17444     59/pop-to-ecx
    17445     58/pop-to-eax
    17446     # . epilogue
    17447     89/<- %esp 5/r32/ebp
    17448     5d/pop-to-ebp
    17449     c3/return
    17450
    17451 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17452     # . prologue
    17453     55/push-ebp
    17454     89/<- %ebp 4/r32/esp
    17455     # if (pos-slice(arr, s) != -1) return it
    17456     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17457     3d/compare-eax-and -1/imm32
    17458     75/jump-if-!= $pos-or-insert-slice:end/disp8
    17459 $pos-or-insert-slice:insert:
    17460     # var s2/eax: (handle array byte)
    17461     68/push 0/imm32
    17462     68/push 0/imm32
    17463     89/<- %eax 4/r32/esp
    17464     (slice-to-string Heap *(ebp+0xc) %eax)
    17465     # throw away alloc-id
    17466     (lookup *eax *(eax+4))  # => eax
    17467     (write-int *(ebp+8) %eax)
    17468     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17469 $pos-or-insert-slice:end:
    17470     # . reclaim locals
    17471     81 0/subop/add %esp 8/imm32
    17472     # . epilogue
    17473     89/<- %esp 5/r32/ebp
    17474     5d/pop-to-ebp
    17475     c3/return
    17476
    17477 # return the index in an array of strings matching 's', -1 if not found
    17478 # index is denominated in elements, not bytes
    17479 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17480     # . prologue
    17481     55/push-ebp
    17482     89/<- %ebp 4/r32/esp
    17483     # . save registers
    17484     51/push-ecx
    17485     52/push-edx
    17486     53/push-ebx
    17487     56/push-esi
    17488 #?     (write-buffered Stderr "pos-slice: ")
    17489 #?     (write-slice-buffered Stderr *(ebp+0xc))
    17490 #?     (write-buffered Stderr "\n")
    17491 #?     (flush Stderr)
    17492     # esi = arr
    17493     8b/-> *(ebp+8) 6/r32/esi
    17494     # var index/ecx: int = 0
    17495     b9/copy-to-ecx 0/imm32
    17496     # var curr/edx: (addr (addr array byte)) = arr->data
    17497     8d/copy-address *(esi+0xc) 2/r32/edx
    17498     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
    17499     8b/-> *esi 3/r32/ebx
    17500     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
    17501     {
    17502 #?       (write-buffered Stderr "  ")
    17503 #?       (write-int32-hex-buffered Stderr %ecx)
    17504 #?       (write-buffered Stderr "\n")
    17505 #?       (flush Stderr)
    17506       # if (curr >= max) return -1
    17507       39/compare %edx 3/r32/ebx
    17508       b8/copy-to-eax -1/imm32
    17509       73/jump-if-addr>= $pos-slice:end/disp8
    17510       # if (slice-equal?(s, *curr)) break
    17511       (slice-equal? *(ebp+0xc) *edx)  # => eax
    17512       3d/compare-eax-and 0/imm32/false
    17513       75/jump-if-!= break/disp8
    17514       # ++index
    17515       41/increment-ecx
    17516       # curr += 4
    17517       81 0/subop/add %edx 4/imm32
    17518       #
    17519       eb/jump loop/disp8
    17520     }
    17521     # return index
    17522     89/<- %eax 1/r32/ecx
    17523 $pos-slice:end:
    17524 #?     (write-buffered Stderr "=> ")
    17525 #?     (write-int32-hex-buffered Stderr %eax)
    17526 #?     (write-buffered Stderr "\n")
    17527     # . restore registers
    17528     5e/pop-to-esi
    17529     5b/pop-to-ebx
    17530     5a/pop-to-edx
    17531     59/pop-to-ecx
    17532     # . epilogue
    17533     89/<- %esp 5/r32/ebp
    17534     5d/pop-to-ebp
    17535     c3/return
    17536
    17537 test-parse-var-with-type:
    17538     # . prologue
    17539     55/push-ebp
    17540     89/<- %ebp 4/r32/esp
    17541     # setup
    17542     8b/-> *Primitive-type-ids 0/r32/eax
    17543     89/<- *Type-id 0/r32/eax  # stream-write
    17544     # (eax..ecx) = "x:"
    17545     b8/copy-to-eax "x:"/imm32
    17546     8b/-> *eax 1/r32/ecx
    17547     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17548     05/add-to-eax 4/imm32
    17549     # var slice/ecx: slice = {eax, ecx}
    17550     51/push-ecx
    17551     50/push-eax
    17552     89/<- %ecx 4/r32/esp
    17553     # _test-input-stream contains "int"
    17554     (clear-stream _test-input-stream)
    17555     (write _test-input-stream "int")
    17556     # var v/edx: (handle var)
    17557     68/push 0/imm32
    17558     68/push 0/imm32
    17559     89/<- %edx 4/r32/esp
    17560     #
    17561     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17562     # var v-addr/edx: (addr var) = lookup(v)
    17563     (lookup *edx *(edx+4))  # => eax
    17564     89/<- %edx 0/r32/eax
    17565     # check v-addr->name
    17566     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17567     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
    17568     # check v-addr->type
    17569     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17570     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
    17571     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
    17572     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
    17573     # . epilogue
    17574     89/<- %esp 5/r32/ebp
    17575     5d/pop-to-ebp
    17576     c3/return
    17577
    17578 test-parse-var-with-type-and-register:
    17579     # . prologue
    17580     55/push-ebp
    17581     89/<- %ebp 4/r32/esp
    17582     # setup
    17583     8b/-> *Primitive-type-ids 0/r32/eax
    17584     89/<- *Type-id 0/r32/eax  # stream-write
    17585     # (eax..ecx) = "x/eax:"
    17586     b8/copy-to-eax "x/eax:"/imm32
    17587     8b/-> *eax 1/r32/ecx
    17588     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17589     05/add-to-eax 4/imm32
    17590     # var slice/ecx: slice = {eax, ecx}
    17591     51/push-ecx
    17592     50/push-eax
    17593     89/<- %ecx 4/r32/esp
    17594     # _test-input-stream contains "int"
    17595     (clear-stream _test-input-stream)
    17596     (write _test-input-stream "int")
    17597     # var v/edx: (handle var)
    17598     68/push 0/imm32
    17599     68/push 0/imm32
    17600     89/<- %edx 4/r32/esp
    17601     #
    17602     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17603     # var v-addr/edx: (addr var) = lookup(v)
    17604     (lookup *edx *(edx+4))  # => eax
    17605     89/<- %edx 0/r32/eax
    17606     # check v-addr->name
    17607     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17608     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
    17609     # check v-addr->register
    17610     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17611     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
    17612     # check v-addr->type
    17613     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17614     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
    17615     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
    17616     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
    17617     # . epilogue
    17618     89/<- %esp 5/r32/ebp
    17619     5d/pop-to-ebp
    17620     c3/return
    17621
    17622 test-parse-var-with-trailing-characters:
    17623     # . prologue
    17624     55/push-ebp
    17625     89/<- %ebp 4/r32/esp
    17626     # setup
    17627     8b/-> *Primitive-type-ids 0/r32/eax
    17628     89/<- *Type-id 0/r32/eax  # stream-write
    17629     # (eax..ecx) = "x:"
    17630     b8/copy-to-eax "x:"/imm32
    17631     8b/-> *eax 1/r32/ecx
    17632     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17633     05/add-to-eax 4/imm32
    17634     # var slice/ecx: slice = {eax, ecx}
    17635     51/push-ecx
    17636     50/push-eax
    17637     89/<- %ecx 4/r32/esp
    17638     # _test-input-stream contains "int,"
    17639     (clear-stream _test-input-stream)
    17640     (write _test-input-stream "int,")
    17641     # var v/edx: (handle var)
    17642     68/push 0/imm32
    17643     68/push 0/imm32
    17644     89/<- %edx 4/r32/esp
    17645     #
    17646     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17647     # var v-addr/edx: (addr var) = lookup(v)
    17648     (lookup *edx *(edx+4))  # => eax
    17649     89/<- %edx 0/r32/eax
    17650     # check v-addr->name
    17651     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17652     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
    17653     # check v-addr->register
    17654     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
    17655     # check v-addr->type
    17656     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17657     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
    17658     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
    17659     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
    17660     # . epilogue
    17661     89/<- %esp 5/r32/ebp
    17662     5d/pop-to-ebp
    17663     c3/return
    17664
    17665 test-parse-var-with-register-and-trailing-characters:
    17666     # . prologue
    17667     55/push-ebp
    17668     89/<- %ebp 4/r32/esp
    17669     # setup
    17670     8b/-> *Primitive-type-ids 0/r32/eax
    17671     89/<- *Type-id 0/r32/eax  # stream-write
    17672     # (eax..ecx) = "x/eax:"
    17673     b8/copy-to-eax "x/eax:"/imm32
    17674     8b/-> *eax 1/r32/ecx
    17675     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17676     05/add-to-eax 4/imm32
    17677     # var slice/ecx: slice = {eax, ecx}
    17678     51/push-ecx
    17679     50/push-eax
    17680     89/<- %ecx 4/r32/esp
    17681     # _test-input-stream contains "int,"
    17682     (clear-stream _test-input-stream)
    17683     (write _test-input-stream "int,")
    17684     # var v/edx: (handle var)
    17685     68/push 0/imm32
    17686     68/push 0/imm32
    17687     89/<- %edx 4/r32/esp
    17688     #
    17689     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17690     # var v-addr/edx: (addr var) = lookup(v)
    17691     (lookup *edx *(edx+4))  # => eax
    17692     89/<- %edx 0/r32/eax
    17693     # check v-addr->name
    17694     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17695     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
    17696     # check v-addr->register
    17697     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17698     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
    17699     # check v-addr->type
    17700     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17701     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
    17702     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
    17703     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
    17704     # . epilogue
    17705     89/<- %esp 5/r32/ebp
    17706     5d/pop-to-ebp
    17707     c3/return
    17708
    17709 test-parse-var-with-compound-type:
    17710     # . prologue
    17711     55/push-ebp
    17712     89/<- %ebp 4/r32/esp
    17713     # setup
    17714     8b/-> *Primitive-type-ids 0/r32/eax
    17715     89/<- *Type-id 0/r32/eax  # stream-write
    17716     # (eax..ecx) = "x:"
    17717     b8/copy-to-eax "x:"/imm32
    17718     8b/-> *eax 1/r32/ecx
    17719     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17720     05/add-to-eax 4/imm32
    17721     # var slice/ecx: slice = {eax, ecx}
    17722     51/push-ecx
    17723     50/push-eax
    17724     89/<- %ecx 4/r32/esp
    17725     # _test-input-stream contains "(addr int)"
    17726     (clear-stream _test-input-stream)
    17727     (write _test-input-stream "(addr int)")
    17728     # var v/edx: (handle var)
    17729     68/push 0/imm32
    17730     68/push 0/imm32
    17731     89/<- %edx 4/r32/esp
    17732     #
    17733     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17734     # var v-addr/edx: (addr var) = lookup(v)
    17735     (lookup *edx *(edx+4))  # => eax
    17736     89/<- %edx 0/r32/eax
    17737     # check v-addr->name
    17738     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17739     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
    17740     # check v-addr->register
    17741     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
    17742     # - check v-addr->type
    17743     # var type/edx: (addr type-tree) = var->type
    17744     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17745     89/<- %edx 0/r32/eax
    17746     # type is a non-atom
    17747     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
    17748     # type->left == atom(addr)
    17749     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    17750     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
    17751     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
    17752     # type->right->left == atom(int)
    17753     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    17754     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    17755     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
    17756     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
    17757     # type->right->right == null
    17758     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
    17759     # . epilogue
    17760     89/<- %esp 5/r32/ebp
    17761     5d/pop-to-ebp
    17762     c3/return
    17763
    17764 # identifier starts with a letter or '$' or '_'
    17765 # no constraints at the moment on later letters
    17766 # all we really want to do so far is exclude '{', '}' and '->'
    17767 identifier?:  # in: (addr slice) -> result/eax: boolean
    17768     # . prologue
    17769     55/push-ebp
    17770     89/<- %ebp 4/r32/esp
    17771     # if (slice-empty?(in)) return false
    17772     (slice-empty? *(ebp+8))  # => eax
    17773     3d/compare-eax-and 0/imm32/false
    17774     75/jump-if-!= $identifier?:false/disp8
    17775     # var c/eax: byte = *in->start
    17776     8b/-> *(ebp+8) 0/r32/eax
    17777     8b/-> *eax 0/r32/eax
    17778     8a/copy-byte *eax 0/r32/AL
    17779     81 4/subop/and %eax 0xff/imm32
    17780     # if (c == '$') return true
    17781     3d/compare-eax-and 0x24/imm32/$
    17782     74/jump-if-= $identifier?:true/disp8
    17783     # if (c == '_') return true
    17784     3d/compare-eax-and 0x5f/imm32/_
    17785     74/jump-if-= $identifier?:true/disp8
    17786     # drop case
    17787     25/and-eax-with 0x5f/imm32
    17788     # if (c < 'A') return false
    17789     3d/compare-eax-and 0x41/imm32/A
    17790     7c/jump-if-< $identifier?:false/disp8
    17791     # if (c > 'Z') return false
    17792     3d/compare-eax-and 0x5a/imm32/Z
    17793     7f/jump-if-> $identifier?:false/disp8
    17794     # otherwise return true
    17795 $identifier?:true:
    17796     b8/copy-to-eax 1/imm32/true
    17797     eb/jump $identifier?:end/disp8
    17798 $identifier?:false:
    17799     b8/copy-to-eax 0/imm32/false
    17800 $identifier?:end:
    17801     # . epilogue
    17802     89/<- %esp 5/r32/ebp
    17803     5d/pop-to-ebp
    17804     c3/return
    17805
    17806 test-is-identifier-dollar:
    17807     # . prologue
    17808     55/push-ebp
    17809     89/<- %ebp 4/r32/esp
    17810     # (eax..ecx) = "$a"
    17811     b8/copy-to-eax "$a"/imm32
    17812     8b/-> *eax 1/r32/ecx
    17813     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17814     05/add-to-eax 4/imm32
    17815     # var slice/ecx: slice = {eax, ecx}
    17816     51/push-ecx
    17817     50/push-eax
    17818     89/<- %ecx 4/r32/esp
    17819     #
    17820     (identifier? %ecx)
    17821     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
    17822     # . epilogue
    17823     89/<- %esp 5/r32/ebp
    17824     5d/pop-to-ebp
    17825     c3/return
    17826
    17827 test-is-identifier-underscore:
    17828     # . prologue
    17829     55/push-ebp
    17830     89/<- %ebp 4/r32/esp
    17831     # (eax..ecx) = "_a"
    17832     b8/copy-to-eax "_a"/imm32
    17833     8b/-> *eax 1/r32/ecx
    17834     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17835     05/add-to-eax 4/imm32
    17836     # var slice/ecx: slice = {eax, ecx}
    17837     51/push-ecx
    17838     50/push-eax
    17839     89/<- %ecx 4/r32/esp
    17840     #
    17841     (identifier? %ecx)
    17842     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
    17843     # . epilogue
    17844     89/<- %esp 5/r32/ebp
    17845     5d/pop-to-ebp
    17846     c3/return
    17847
    17848 test-is-identifier-a:
    17849     # . prologue
    17850     55/push-ebp
    17851     89/<- %ebp 4/r32/esp
    17852     # (eax..ecx) = "a$"
    17853     b8/copy-to-eax "a$"/imm32
    17854     8b/-> *eax 1/r32/ecx
    17855     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17856     05/add-to-eax 4/imm32
    17857     # var slice/ecx: slice = {eax, ecx}
    17858     51/push-ecx
    17859     50/push-eax
    17860     89/<- %ecx 4/r32/esp
    17861     #
    17862     (identifier? %ecx)
    17863     (check-ints-equal %eax 1 "F - test-is-identifier-a")
    17864     # . epilogue
    17865     89/<- %esp 5/r32/ebp
    17866     5d/pop-to-ebp
    17867     c3/return
    17868
    17869 test-is-identifier-z:
    17870     # . prologue
    17871     55/push-ebp
    17872     89/<- %ebp 4/r32/esp
    17873     # (eax..ecx) = "z$"
    17874     b8/copy-to-eax "z$"/imm32
    17875     8b/-> *eax 1/r32/ecx
    17876     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17877     05/add-to-eax 4/imm32
    17878     # var slice/ecx: slice = {eax, ecx}
    17879     51/push-ecx
    17880     50/push-eax
    17881     89/<- %ecx 4/r32/esp
    17882     #
    17883     (identifier? %ecx)
    17884     (check-ints-equal %eax 1 "F - test-is-identifier-z")
    17885     # . epilogue
    17886     89/<- %esp 5/r32/ebp
    17887     5d/pop-to-ebp
    17888     c3/return
    17889
    17890 test-is-identifier-A:
    17891     # . prologue
    17892     55/push-ebp
    17893     89/<- %ebp 4/r32/esp
    17894     # (eax..ecx) = "A$"
    17895     b8/copy-to-eax "A$"/imm32
    17896     8b/-> *eax 1/r32/ecx
    17897     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17898     05/add-to-eax 4/imm32
    17899     # var slice/ecx: slice = {eax, ecx}
    17900     51/push-ecx
    17901     50/push-eax
    17902     89/<- %ecx 4/r32/esp
    17903     #
    17904     (identifier? %ecx)
    17905     (check-ints-equal %eax 1 "F - test-is-identifier-A")
    17906     # . epilogue
    17907     89/<- %esp 5/r32/ebp
    17908     5d/pop-to-ebp
    17909     c3/return
    17910
    17911 test-is-identifier-Z:
    17912     # . prologue
    17913     55/push-ebp
    17914     89/<- %ebp 4/r32/esp
    17915     # (eax..ecx) = "Z$"
    17916     b8/copy-to-eax "Z$"/imm32
    17917     8b/-> *eax 1/r32/ecx
    17918     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17919     05/add-to-eax 4/imm32
    17920     # var slice/ecx: slice = {eax, ecx}
    17921     51/push-ecx
    17922     50/push-eax
    17923     89/<- %ecx 4/r32/esp
    17924     #
    17925     (identifier? %ecx)
    17926     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
    17927     # . epilogue
    17928     89/<- %esp 5/r32/ebp
    17929     5d/pop-to-ebp
    17930     c3/return
    17931
    17932 test-is-identifier-at:
    17933     # character before 'A' is invalid
    17934     # . prologue
    17935     55/push-ebp
    17936     89/<- %ebp 4/r32/esp
    17937     # (eax..ecx) = "@a"
    17938     b8/copy-to-eax "@a"/imm32
    17939     8b/-> *eax 1/r32/ecx
    17940     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17941     05/add-to-eax 4/imm32
    17942     # var slice/ecx: slice = {eax, ecx}
    17943     51/push-ecx
    17944     50/push-eax
    17945     89/<- %ecx 4/r32/esp
    17946     #
    17947     (identifier? %ecx)
    17948     (check-ints-equal %eax 0 "F - test-is-identifier-@")
    17949     # . epilogue
    17950     89/<- %esp 5/r32/ebp
    17951     5d/pop-to-ebp
    17952     c3/return
    17953
    17954 test-is-identifier-square-bracket:
    17955     # character after 'Z' is invalid
    17956     # . prologue
    17957     55/push-ebp
    17958     89/<- %ebp 4/r32/esp
    17959     # (eax..ecx) = "[a"
    17960     b8/copy-to-eax "[a"/imm32
    17961     8b/-> *eax 1/r32/ecx
    17962     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17963     05/add-to-eax 4/imm32
    17964     # var slice/ecx: slice = {eax, ecx}
    17965     51/push-ecx
    17966     50/push-eax
    17967     89/<- %ecx 4/r32/esp
    17968     #
    17969     (identifier? %ecx)
    17970     (check-ints-equal %eax 0 "F - test-is-identifier-@")
    17971     # . epilogue
    17972     89/<- %esp 5/r32/ebp
    17973     5d/pop-to-ebp
    17974     c3/return
    17975
    17976 test-is-identifier-backtick:
    17977     # character before 'a' is invalid
    17978     # . prologue
    17979     55/push-ebp
    17980     89/<- %ebp 4/r32/esp
    17981     # (eax..ecx) = "`a"
    17982     b8/copy-to-eax "`a"/imm32
    17983     8b/-> *eax 1/r32/ecx
    17984     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17985     05/add-to-eax 4/imm32
    17986     # var slice/ecx: slice = {eax, ecx}
    17987     51/push-ecx
    17988     50/push-eax
    17989     89/<- %ecx 4/r32/esp
    17990     #
    17991     (identifier? %ecx)
    17992     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
    17993     # . epilogue
    17994     89/<- %esp 5/r32/ebp
    17995     5d/pop-to-ebp
    17996     c3/return
    17997
    17998 test-is-identifier-curly-brace-open:
    17999     # character after 'z' is invalid; also used for blocks
    18000     # . prologue
    18001     55/push-ebp
    18002     89/<- %ebp 4/r32/esp
    18003     # (eax..ecx) = "{a"
    18004     b8/copy-to-eax "{a"/imm32
    18005     8b/-> *eax 1/r32/ecx
    18006     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18007     05/add-to-eax 4/imm32
    18008     # var slice/ecx: slice = {eax, ecx}
    18009     51/push-ecx
    18010     50/push-eax
    18011     89/<- %ecx 4/r32/esp
    18012     #
    18013     (identifier? %ecx)
    18014     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
    18015     # . epilogue
    18016     89/<- %esp 5/r32/ebp
    18017     5d/pop-to-ebp
    18018     c3/return
    18019
    18020 test-is-identifier-curly-brace-close:
    18021     # . prologue
    18022     55/push-ebp
    18023     89/<- %ebp 4/r32/esp
    18024     # (eax..ecx) = "}a"
    18025     b8/copy-to-eax "}a"/imm32
    18026     8b/-> *eax 1/r32/ecx
    18027     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18028     05/add-to-eax 4/imm32
    18029     # var slice/ecx: slice = {eax, ecx}
    18030     51/push-ecx
    18031     50/push-eax
    18032     89/<- %ecx 4/r32/esp
    18033     #
    18034     (identifier? %ecx)
    18035     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
    18036     # . epilogue
    18037     89/<- %esp 5/r32/ebp
    18038     5d/pop-to-ebp
    18039     c3/return
    18040
    18041 test-is-identifier-hyphen:
    18042     # disallow leading '-' since '->' has special meaning
    18043     # . prologue
    18044     55/push-ebp
    18045     89/<- %ebp 4/r32/esp
    18046     # (eax..ecx) = "-a"
    18047     b8/copy-to-eax "-a"/imm32
    18048     8b/-> *eax 1/r32/ecx
    18049     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18050     05/add-to-eax 4/imm32
    18051     # var slice/ecx: slice = {eax, ecx}
    18052     51/push-ecx
    18053     50/push-eax
    18054     89/<- %ecx 4/r32/esp
    18055     #
    18056     (identifier? %ecx)
    18057     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
    18058     # . epilogue
    18059     89/<- %esp 5/r32/ebp
    18060     5d/pop-to-ebp
    18061     c3/return
    18062
    18063 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
    18064     # . prologue
    18065     55/push-ebp
    18066     89/<- %ebp 4/r32/esp
    18067     # . save registers
    18068     50/push-eax
    18069     56/push-esi
    18070     57/push-edi
    18071     # esi = in
    18072     8b/-> *(ebp+8) 6/r32/esi
    18073     # edi = out
    18074     8b/-> *(ebp+0xc) 7/r32/edi
    18075     # initialize some global state
    18076     c7 0/subop/copy *Curr-block-depth 1/imm32
    18077     # parse-mu-block(in, vars, out, out->body)
    18078     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
    18079     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
    18080 $populate-mu-function-body:end:
    18081     # . restore registers
    18082     5f/pop-to-edi
    18083     5e/pop-to-esi
    18084     58/pop-to-eax
    18085     # . epilogue
    18086     89/<- %esp 5/r32/ebp
    18087     5d/pop-to-ebp
    18088     c3/return
    18089
    18090 # parses a block, assuming that the leading '{' has already been read by the caller
    18091 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)
    18092     # pseudocode:
    18093     #   var line: (stream byte 512)
    18094     #   var word-slice: slice
    18095     #   allocate(Heap, Stmt-size, out)
    18096     #   var out-addr: (addr block) = lookup(*out)
    18097     #   out-addr->tag = 0/block
    18098     #   out-addr->var = some unique name
    18099     #   push(vars, {out-addr->var, false})
    18100     #   while true                                  # line loop
    18101     #     clear-stream(line)
    18102     #     read-line-buffered(in, line)
    18103     #     if (line->write == 0) break               # end of file
    18104     #     word-slice = next-mu-token(line)
    18105     #     if slice-empty?(word-slice)               # end of line
    18106     #       continue
    18107     #     else if slice-starts-with?(word-slice, "#")
    18108     #       continue
    18109     #     else if slice-equal?(word-slice, "{")
    18110     #       assert(no-tokens-in(line))
    18111     #       block = parse-mu-block(in, vars, fn)
    18112     #       append-to-block(out-addr, block)
    18113     #     else if slice-equal?(word-slice, "}")
    18114     #       break
    18115     #     else if slice-ends-with?(word-slice, ":")
    18116     #       # TODO: error-check the rest of 'line'
    18117     #       --word-slice->end to skip ':'
    18118     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
    18119     #       append-to-block(out-addr, named-block)
    18120     #     else if slice-equal?(word-slice, "var")
    18121     #       var-def = parse-mu-var-def(line, vars, fn)
    18122     #       append-to-block(out-addr, var-def)
    18123     #     else
    18124     #       stmt = parse-mu-stmt(line, vars, fn)
    18125     #       append-to-block(out-addr, stmt)
    18126     #   pop(vars)
    18127     #
    18128     # . prologue
    18129     55/push-ebp
    18130     89/<- %ebp 4/r32/esp
    18131     # . save registers
    18132     50/push-eax
    18133     51/push-ecx
    18134     52/push-edx
    18135     53/push-ebx
    18136     57/push-edi
    18137     # var line/ecx: (stream byte 512)
    18138     81 5/subop/subtract %esp 0x200/imm32
    18139     68/push 0x200/imm32/size
    18140     68/push 0/imm32/read
    18141     68/push 0/imm32/write
    18142     89/<- %ecx 4/r32/esp
    18143     # var word-slice/edx: slice
    18144     68/push 0/imm32/end
    18145     68/push 0/imm32/start
    18146     89/<- %edx 4/r32/esp
    18147     # allocate into out
    18148     (allocate Heap *Stmt-size *(ebp+0x14))
    18149     # var out-addr/edi: (addr block) = lookup(*out)
    18150     8b/-> *(ebp+0x14) 7/r32/edi
    18151     (lookup *edi *(edi+4))  # => eax
    18152     89/<- %edi 0/r32/eax
    18153     # out-addr->tag is 0 (block) by default
    18154     # set out-addr->var
    18155     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
    18156     (new-block-name *(ebp+0x10) %eax)
    18157     # push(vars, out-addr->var)
    18158     (push *(ebp+0xc) *(edi+0xc))  # Block-var
    18159     (push *(ebp+0xc) *(edi+0x10))  # Block-var
    18160     (push *(ebp+0xc) 0)  # false
    18161     # increment *Curr-block-depth
    18162     ff 0/subop/increment *Curr-block-depth
    18163     {
    18164 $parse-mu-block:line-loop:
    18165       # line = read-line-buffered(in)
    18166       (clear-stream %ecx)
    18167       (read-line-buffered *(ebp+8) %ecx)
    18168 #?       (write-buffered Stderr "line: ")
    18169 #?       (write-stream-data Stderr %ecx)
    18170 #? #?       (write-buffered Stderr Newline)  # line has its own newline
    18171 #?       (flush Stderr)
    18172 #?       (rewind-stream %ecx)
    18173       # if (line->write == 0) break
    18174       81 7/subop/compare *ecx 0/imm32
    18175       0f 84/jump-if-= break/disp32
    18176 #?       (write-buffered Stderr "vars:\n")
    18177 #?       (dump-vars *(ebp+0xc))
    18178       # word-slice = next-mu-token(line)
    18179       (next-mu-token %ecx %edx)
    18180 #?       (write-buffered Stderr "word: ")
    18181 #?       (write-slice-buffered Stderr %edx)
    18182 #?       (write-buffered Stderr Newline)
    18183 #?       (flush Stderr)
    18184       # if slice-empty?(word-slice) continue
    18185       (slice-empty? %edx)
    18186       3d/compare-eax-and 0/imm32/false
    18187       0f 85/jump-if-!= loop/disp32
    18188       # if (slice-starts-with?(word-slice, '#') continue
    18189       # . eax = *word-slice->start
    18190       8b/-> *edx 0/r32/eax
    18191       8a/copy-byte *eax 0/r32/AL
    18192       81 4/subop/and %eax 0xff/imm32
    18193       # . if (eax == '#') continue
    18194       3d/compare-eax-and 0x23/imm32/hash
    18195       0f 84/jump-if-= loop/disp32
    18196       # if slice-equal?(word-slice, "{")
    18197       {
    18198 $parse-mu-block:check-for-block:
    18199         (slice-equal? %edx "{")
    18200         3d/compare-eax-and 0/imm32/false
    18201         74/jump-if-= break/disp8
    18202         (check-no-tokens-left %ecx)
    18203         # parse new block and append
    18204         # . var tmp/eax: (handle block)
    18205         68/push 0/imm32
    18206         68/push 0/imm32
    18207         89/<- %eax 4/r32/esp
    18208         # .
    18209         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18210         (append-to-block Heap %edi  *eax *(eax+4))
    18211         # . reclaim tmp
    18212         81 0/subop/add %esp 8/imm32
    18213         # .
    18214         e9/jump $parse-mu-block:line-loop/disp32
    18215       }
    18216       # if slice-equal?(word-slice, "}") break
    18217 $parse-mu-block:check-for-end:
    18218       (slice-equal? %edx "}")
    18219       3d/compare-eax-and 0/imm32/false
    18220       0f 85/jump-if-!= break/disp32
    18221       # if slice-ends-with?(word-slice, ":") parse named block and append
    18222       {
    18223 $parse-mu-block:check-for-named-block:
    18224         # . eax = *(word-slice->end-1)
    18225         8b/-> *(edx+4) 0/r32/eax
    18226         48/decrement-eax
    18227         8a/copy-byte *eax 0/r32/AL
    18228         81 4/subop/and %eax 0xff/imm32
    18229         # . if (eax != ':') break
    18230         3d/compare-eax-and 0x3a/imm32/colon
    18231         0f 85/jump-if-!= break/disp32
    18232         # TODO: error-check the rest of 'line'
    18233         #
    18234         # skip ':'
    18235         ff 1/subop/decrement *(edx+4)  # Slice-end
    18236         # var tmp/eax: (handle block)
    18237         68/push 0/imm32
    18238         68/push 0/imm32
    18239         89/<- %eax 4/r32/esp
    18240         #
    18241         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18242         (append-to-block Heap %edi  *eax *(eax+4))
    18243         # reclaim tmp
    18244         81 0/subop/add %esp 8/imm32
    18245         #
    18246         e9/jump $parse-mu-block:line-loop/disp32
    18247       }
    18248       # if slice-equal?(word-slice, "var")
    18249       {
    18250 $parse-mu-block:check-for-var:
    18251         (slice-equal? %edx "var")
    18252         3d/compare-eax-and 0/imm32/false
    18253         74/jump-if-= break/disp8
    18254         # var tmp/eax: (handle block)
    18255         68/push 0/imm32
    18256         68/push 0/imm32
    18257         89/<- %eax 4/r32/esp
    18258         #
    18259         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18260         (append-to-block Heap %edi  *eax *(eax+4))
    18261         # reclaim tmp
    18262         81 0/subop/add %esp 8/imm32
    18263         #
    18264         e9/jump $parse-mu-block:line-loop/disp32
    18265       }
    18266 $parse-mu-block:regular-stmt:
    18267       # otherwise
    18268       # var tmp/eax: (handle block)
    18269       68/push 0/imm32
    18270       68/push 0/imm32
    18271       89/<- %eax 4/r32/esp
    18272       #
    18273       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18274       (append-to-block Heap %edi  *eax *(eax+4))
    18275       # reclaim tmp
    18276       81 0/subop/add %esp 8/imm32
    18277       #
    18278       e9/jump loop/disp32
    18279     } # end line loop
    18280     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
    18281     # decrement *Curr-block-depth
    18282     ff 1/subop/decrement *Curr-block-depth
    18283     # pop(vars)
    18284     (pop *(ebp+0xc))  # => eax
    18285     (pop *(ebp+0xc))  # => eax
    18286     (pop *(ebp+0xc))  # => eax
    18287 $parse-mu-block:end:
    18288     # . reclaim locals
    18289     81 0/subop/add %esp 0x214/imm32
    18290     # . restore registers
    18291     5f/pop-to-edi
    18292     5b/pop-to-ebx
    18293     5a/pop-to-edx
    18294     59/pop-to-ecx
    18295     58/pop-to-eax
    18296     # . epilogue
    18297     89/<- %esp 5/r32/ebp
    18298     5d/pop-to-ebp
    18299     c3/return
    18300
    18301 $parse-mu-block:abort:
    18302     # error("'{' or '}' should be on its own line, but got '")
    18303     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
    18304     (rewind-stream %ecx)
    18305     (write-stream-data *(ebp+0x18) %ecx)
    18306     (write-buffered *(ebp+0x18) "'\n")
    18307     (flush *(ebp+0x18))
    18308     (stop *(ebp+0x1c) 1)
    18309     # never gets here
    18310
    18311 new-block-name:  # fn: (addr function), out: (addr handle var)
    18312     # . prologue
    18313     55/push-ebp
    18314     89/<- %ebp 4/r32/esp
    18315     # . save registers
    18316     50/push-eax
    18317     51/push-ecx
    18318     52/push-edx
    18319     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
    18320     8b/-> *(ebp+8) 0/r32/eax
    18321     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18322     8b/-> *eax 0/r32/eax  # String-size
    18323     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
    18324     89/<- %ecx 0/r32/eax
    18325     # var name/edx: (stream byte n)
    18326     29/subtract-from %esp 1/r32/ecx
    18327     ff 6/subop/push %ecx
    18328     68/push 0/imm32/read
    18329     68/push 0/imm32/write
    18330     89/<- %edx 4/r32/esp
    18331     (clear-stream %edx)
    18332     # eax = fn->name
    18333     8b/-> *(ebp+8) 0/r32/eax
    18334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18335     # construct result using Next-block-index (and increment it)
    18336     (write %edx "$")
    18337     (write %edx %eax)
    18338     (write %edx ":")
    18339     (write-int32-hex %edx *Next-block-index)
    18340     ff 0/subop/increment *Next-block-index
    18341     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
    18342     # . eax = name->write
    18343     8b/-> *edx 0/r32/eax
    18344     # . edx = name->data
    18345     8d/copy-address *(edx+0xc) 2/r32/edx
    18346     # . eax = name->write + name->data
    18347     01/add-to %eax 2/r32/edx
    18348     # . push {edx, eax}
    18349     ff 6/subop/push %eax
    18350     ff 6/subop/push %edx
    18351     89/<- %eax 4/r32/esp
    18352     # out = new literal(s)
    18353     (new-literal Heap %eax *(ebp+0xc))
    18354 #?     8b/-> *(ebp+0xc) 0/r32/eax
    18355 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
    18356 #?     (write-int32-hex-buffered Stderr *(eax+8))
    18357 #?     (write-buffered Stderr " for var ")
    18358 #?     (write-int32-hex-buffered Stderr %eax)
    18359 #?     (write-buffered Stderr Newline)
    18360 #?     (flush Stderr)
    18361 $new-block-name:end:
    18362     # . reclaim locals
    18363     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
    18364     81 0/subop/add %ecx 8/imm32  # slice
    18365     01/add-to %esp 1/r32/ecx
    18366     # . restore registers
    18367     5a/pop-to-edx
    18368     59/pop-to-ecx
    18369     58/pop-to-eax
    18370     # . epilogue
    18371     89/<- %esp 5/r32/ebp
    18372     5d/pop-to-ebp
    18373     c3/return
    18374
    18375 check-no-tokens-left:  # line: (addr stream byte)
    18376     # . prologue
    18377     55/push-ebp
    18378     89/<- %ebp 4/r32/esp
    18379     # . save registers
    18380     50/push-eax
    18381     51/push-ecx
    18382     # var s/ecx: slice
    18383     68/push 0/imm32/end
    18384     68/push 0/imm32/start
    18385     89/<- %ecx 4/r32/esp
    18386     #
    18387     (next-mu-token *(ebp+8) %ecx)
    18388     # if slice-empty?(s) return
    18389     (slice-empty? %ecx)
    18390     3d/compare-eax-and 0/imm32/false
    18391     75/jump-if-!= $check-no-tokens-left:end/disp8
    18392     # if (slice-starts-with?(s, '#') return
    18393     # . eax = *s->start
    18394     8b/-> *edx 0/r32/eax
    18395     8a/copy-byte *eax 0/r32/AL
    18396     81 4/subop/and %eax 0xff/imm32
    18397     # . if (eax == '#') continue
    18398     3d/compare-eax-and 0x23/imm32/hash
    18399     74/jump-if-= $check-no-tokens-left:end/disp8
    18400     # abort
    18401     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
    18402     (rewind-stream %ecx)
    18403     (write-stream 2 %ecx)
    18404     (write-buffered Stderr "'\n")
    18405     (flush Stderr)
    18406     # . syscall(exit, 1)
    18407     bb/copy-to-ebx  1/imm32
    18408     e8/call syscall_exit/disp32
    18409     # never gets here
    18410 $check-no-tokens-left:end:
    18411     # . reclaim locals
    18412     81 0/subop/add %esp 8/imm32
    18413     # . restore registers
    18414     59/pop-to-ecx
    18415     58/pop-to-eax
    18416     # . epilogue
    18417     89/<- %esp 5/r32/ebp
    18418     5d/pop-to-ebp
    18419     c3/return
    18420
    18421 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)
    18422     # pseudocode:
    18423     #   var v: (handle var)
    18424     #   new-literal(name, v)
    18425     #   push(vars, {v, false})
    18426     #   parse-mu-block(in, vars, fn, out)
    18427     #   pop(vars)
    18428     #   out->tag = block
    18429     #   out->var = v
    18430     #
    18431     # . prologue
    18432     55/push-ebp
    18433     89/<- %ebp 4/r32/esp
    18434     # . save registers
    18435     50/push-eax
    18436     51/push-ecx
    18437     57/push-edi
    18438     # var v/ecx: (handle var)
    18439     68/push 0/imm32
    18440     68/push 0/imm32
    18441     89/<- %ecx 4/r32/esp
    18442     #
    18443     (new-literal Heap *(ebp+8) %ecx)
    18444     # push(vars, v)
    18445     (push *(ebp+0x10) *ecx)
    18446     (push *(ebp+0x10) *(ecx+4))
    18447     (push *(ebp+0x10) 0)  # false
    18448     #
    18449     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
    18450     # pop v off vars
    18451     (pop *(ebp+0x10))  # => eax
    18452     (pop *(ebp+0x10))  # => eax
    18453     (pop *(ebp+0x10))  # => eax
    18454     # var out-addr/edi: (addr stmt) = lookup(*out)
    18455     8b/-> *(ebp+0x18) 7/r32/edi
    18456     (lookup *edi *(edi+4))  # => eax
    18457     89/<- %edi 0/r32/eax
    18458     # out-addr->tag = named-block
    18459     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
    18460     # out-addr->var = v
    18461     8b/-> *ecx 0/r32/eax
    18462     89/<- *(edi+0xc) 0/r32/eax  # Block-var
    18463     8b/-> *(ecx+4) 0/r32/eax
    18464     89/<- *(edi+0x10) 0/r32/eax  # Block-var
    18465 $parse-mu-named-block:end:
    18466     # . reclaim locals
    18467     81 0/subop/add %esp 8/imm32
    18468     # . restore registers
    18469     5f/pop-to-edi
    18470     59/pop-to-ecx
    18471     58/pop-to-eax
    18472     # . epilogue
    18473     89/<- %esp 5/r32/ebp
    18474     5d/pop-to-ebp
    18475     c3/return
    18476
    18477 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)
    18478     # . prologue
    18479     55/push-ebp
    18480     89/<- %ebp 4/r32/esp
    18481     # . save registers
    18482     50/push-eax
    18483     51/push-ecx
    18484     52/push-edx
    18485     56/push-esi
    18486     57/push-edi
    18487     # edi = out
    18488     8b/-> *(ebp+0x10) 7/r32/edi
    18489     # var word-slice/ecx: slice
    18490     68/push 0/imm32/end
    18491     68/push 0/imm32/start
    18492     89/<- %ecx 4/r32/esp
    18493     # var v/edx: (handle var)
    18494     68/push 0/imm32
    18495     68/push 0/imm32
    18496     89/<- %edx 4/r32/esp
    18497     # v = parse-var-with-type(next-mu-token(line))
    18498     (next-mu-token *(ebp+8) %ecx)
    18499     {
    18500       # just for tests, support null fn
    18501       8b/-> *(ebp+0x14) 0/r32/eax
    18502       3d/compare-eax-and 0/imm32
    18503       74/jump-if-= break/disp8
    18504       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18505     }
    18506     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
    18507     # var v-addr/esi: (addr var)
    18508     (lookup *edx *(edx+4))  # => eax
    18509     89/<- %esi 0/r32/eax
    18510     # v->block-depth = *Curr-block-depth
    18511     8b/-> *Curr-block-depth 0/r32/eax
    18512     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
    18513     # either v has no register and there's no more to this line
    18514     81 7/subop/compare *(esi+0x18) 0/imm32
    18515     {
    18516       75/jump-if-!= break/disp8
    18517       # if v-addr->type == byte, abort
    18518       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18519       (simple-mu-type? %eax 8)  # byte => eax
    18520       3d/compare-eax-and 0/imm32/false
    18521       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
    18522       # ensure that there's nothing else on this line
    18523       (next-mu-token *(ebp+8) %ecx)
    18524       (slice-empty? %ecx)  # => eax
    18525       3d/compare-eax-and 0/imm32/false
    18526       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
    18527       #
    18528       (new-var-def Heap  *edx *(edx+4)  %edi)
    18529       e9/jump $parse-mu-var-def:update-vars/disp32
    18530     }
    18531     # or v has a register and there's more to this line
    18532     {
    18533       0f 84/jump-if-= break/disp32
    18534       # if v-addr->type == byte, check for unsupported registers
    18535       {
    18536         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18537         (simple-mu-type? %eax 8)  # byte => eax
    18538         3d/compare-eax-and 0/imm32/false
    18539         74/jump-if-= break/disp8
    18540         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18541         (string-equal? %eax "esi")  # => eax
    18542         3d/compare-eax-and 0/imm32/false
    18543         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18544         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18545         (string-equal? %eax "edi")  # => eax
    18546         3d/compare-eax-and 0/imm32/false
    18547         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18548       }
    18549       # TODO: vars of type 'byte' should only be initialized by clearing to 0
    18550       # ensure that the next word is '<-'
    18551       (next-mu-token *(ebp+8) %ecx)
    18552       (slice-equal? %ecx "<-")  # => eax
    18553       3d/compare-eax-and 0/imm32/false
    18554       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
    18555       #
    18556       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
    18557       (lookup *edi *(edi+4))  # => eax
    18558       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18559     }
    18560 $parse-mu-var-def:update-vars:
    18561     # push 'v' at end of function
    18562     (push *(ebp+0xc) *edx)
    18563     (push *(ebp+0xc) *(edx+4))
    18564     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
    18565 $parse-mu-var-def:end:
    18566     # . reclaim locals
    18567     81 0/subop/add %esp 0x10/imm32
    18568     # . restore registers
    18569     5f/pop-to-edi
    18570     5e/pop-to-esi
    18571     5a/pop-to-edx
    18572     59/pop-to-ecx
    18573     58/pop-to-eax
    18574     # . epilogue
    18575     89/<- %esp 5/r32/ebp
    18576     5d/pop-to-ebp
    18577     c3/return
    18578
    18579 $parse-mu-var-def:error1:
    18580     (rewind-stream *(ebp+8))
    18581     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
    18582     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
    18583     (flush *(ebp+0x18))
    18584     (write-stream-data *(ebp+0x18) *(ebp+8))
    18585     (write-buffered *(ebp+0x18) "'\n")
    18586     (flush *(ebp+0x18))
    18587     (stop *(ebp+0x1c) 1)
    18588     # never gets here
    18589
    18590 $parse-mu-var-def:error2:
    18591     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
    18592     (write-buffered *(ebp+0x18) "fn ")
    18593     8b/-> *(ebp+0x14) 0/r32/eax
    18594     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18595     (write-buffered *(ebp+0x18) %eax)
    18596     (write-buffered *(ebp+0x18) ": var ")
    18597     # var v-addr/eax: (addr var) = lookup(v)
    18598     (lookup *edx *(edx+4))  # => eax
    18599     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18600     (write-buffered *(ebp+0x18) %eax)
    18601     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
    18602     (flush *(ebp+0x18))
    18603     (stop *(ebp+0x1c) 1)
    18604     # never gets here
    18605
    18606 $parse-mu-var-def:error-byte-on-stack:
    18607     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
    18608     (write-buffered *(ebp+0x18) "fn ")
    18609     8b/-> *(ebp+0x14) 0/r32/eax
    18610     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18611     (write-buffered *(ebp+0x18) %eax)
    18612     (write-buffered *(ebp+0x18) ": var '")
    18613     # var v-addr/eax: (addr var) = lookup(v)
    18614     (lookup *edx *(edx+4))  # => eax
    18615     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18616     (write-buffered *(ebp+0x18) %eax)
    18617     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
    18618     (flush *(ebp+0x18))
    18619     (stop *(ebp+0x1c) 1)
    18620     # never gets here
    18621
    18622 $parse-mu-var-def:error-byte-registers:
    18623     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
    18624     (write-buffered *(ebp+0x18) "fn ")
    18625     8b/-> *(ebp+0x14) 0/r32/eax
    18626     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18627     (write-buffered *(ebp+0x18) %eax)
    18628     (write-buffered *(ebp+0x18) ": var '")
    18629     # var v-addr/eax: (addr var) = lookup(v)
    18630     (lookup *edx *(edx+4))  # => eax
    18631     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18632     (write-buffered *(ebp+0x18) %eax)
    18633     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
    18634     (flush *(ebp+0x18))
    18635     (stop *(ebp+0x1c) 1)
    18636     # never gets here
    18637
    18638 test-parse-mu-var-def:
    18639     # 'var n: int'
    18640     # . prologue
    18641     55/push-ebp
    18642     89/<- %ebp 4/r32/esp
    18643     # setup
    18644     8b/-> *Primitive-type-ids 0/r32/eax
    18645     89/<- *Type-id 0/r32/eax  # stream-write
    18646     (clear-stream _test-input-stream)
    18647     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
    18648     c7 0/subop/copy *Curr-block-depth 1/imm32
    18649     # var out/esi: (handle stmt)
    18650     68/push 0/imm32
    18651     68/push 0/imm32
    18652     89/<- %esi 4/r32/esp
    18653     # var vars/ecx: (stack (addr var) 16)
    18654     81 5/subop/subtract %esp 0xc0/imm32
    18655     68/push 0xc0/imm32/size
    18656     68/push 0/imm32/top
    18657     89/<- %ecx 4/r32/esp
    18658     (clear-stack %ecx)
    18659     # convert
    18660     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18661     # var out-addr/esi: (addr stmt)
    18662     (lookup *esi *(esi+4))  # => eax
    18663     89/<- %esi 0/r32/eax
    18664     #
    18665     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
    18666     # var v/ecx: (addr var) = lookup(out->var)
    18667     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
    18668     89/<- %ecx 0/r32/eax
    18669     # v->name
    18670     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18671     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
    18672     # v->register
    18673     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
    18674     # v->block-depth
    18675     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
    18676     # v->type == int
    18677     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18678     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
    18679     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
    18680     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
    18681     # . epilogue
    18682     89/<- %esp 5/r32/ebp
    18683     5d/pop-to-ebp
    18684     c3/return
    18685
    18686 test-parse-mu-reg-var-def:
    18687     # 'var n/eax: int <- copy 0'
    18688     # . prologue
    18689     55/push-ebp
    18690     89/<- %ebp 4/r32/esp
    18691     # setup
    18692     8b/-> *Primitive-type-ids 0/r32/eax
    18693     89/<- *Type-id 0/r32/eax  # stream-write
    18694     (clear-stream _test-input-stream)
    18695     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
    18696     c7 0/subop/copy *Curr-block-depth 1/imm32
    18697     # var out/esi: (handle stmt)
    18698     68/push 0/imm32
    18699     68/push 0/imm32
    18700     89/<- %esi 4/r32/esp
    18701     # var vars/ecx: (stack (addr var) 16)
    18702     81 5/subop/subtract %esp 0xc0/imm32
    18703     68/push 0xc0/imm32/size
    18704     68/push 0/imm32/top
    18705     89/<- %ecx 4/r32/esp
    18706     (clear-stack %ecx)
    18707     # convert
    18708     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18709     # var out-addr/esi: (addr stmt)
    18710     (lookup *esi *(esi+4))  # => eax
    18711     89/<- %esi 0/r32/eax
    18712     #
    18713     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
    18714     # var v/ecx: (addr var) = lookup(out->outputs->value)
    18715     # . eax: (addr stmt-var) = lookup(out->outputs)
    18716     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    18717     # .
    18718     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
    18719     # . eax: (addr var) = lookup(eax->value)
    18720     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    18721     # . ecx = eax
    18722     89/<- %ecx 0/r32/eax
    18723     # v->name
    18724     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18725     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
    18726     # v->register
    18727     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    18728     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
    18729     # v->block-depth
    18730     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
    18731     # v->type == int
    18732     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18733     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
    18734     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
    18735     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
    18736     # . epilogue
    18737     89/<- %esp 5/r32/ebp
    18738     5d/pop-to-ebp
    18739     c3/return
    18740
    18741 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)
    18742     # pseudocode:
    18743     #   var name: slice
    18744     #   allocate(Heap, Stmt-size, out)
    18745     #   var out-addr: (addr stmt) = lookup(*out)
    18746     #   out-addr->tag = stmt
    18747     #   if stmt-has-outputs?(line)
    18748     #     while true
    18749     #       name = next-mu-token(line)
    18750     #       if (name == '<-') break
    18751     #       assert(identifier?(name))
    18752     #       var v: (handle var) = lookup-var(name, vars)
    18753     #       out-addr->outputs = append(v, out-addr->outputs)
    18754     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
    18755     #
    18756     # . prologue
    18757     55/push-ebp
    18758     89/<- %ebp 4/r32/esp
    18759     # . save registers
    18760     50/push-eax
    18761     51/push-ecx
    18762     52/push-edx
    18763     53/push-ebx
    18764     57/push-edi
    18765     # var name/ecx: slice
    18766     68/push 0/imm32/end
    18767     68/push 0/imm32/start
    18768     89/<- %ecx 4/r32/esp
    18769     # var is-deref?/edx: boolean = false
    18770     ba/copy-to-edx 0/imm32/false
    18771     # var v: (handle var)
    18772     68/push 0/imm32
    18773     68/push 0/imm32
    18774     89/<- %ebx 4/r32/esp
    18775     #
    18776     (allocate Heap *Stmt-size *(ebp+0x14))
    18777     # var out-addr/edi: (addr stmt) = lookup(*out)
    18778     8b/-> *(ebp+0x14) 7/r32/edi
    18779     (lookup *edi *(edi+4))  # => eax
    18780     89/<- %edi 0/r32/eax
    18781     # out-addr->tag = 1/stmt
    18782     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
    18783     {
    18784       (stmt-has-outputs? *(ebp+8))
    18785       3d/compare-eax-and 0/imm32/false
    18786       0f 84/jump-if-= break/disp32
    18787       {
    18788 $parse-mu-stmt:read-outputs:
    18789         # name = next-mu-token(line)
    18790         (next-mu-token *(ebp+8) %ecx)
    18791         # if slice-empty?(word-slice) break
    18792         (slice-empty? %ecx)  # => eax
    18793         3d/compare-eax-and 0/imm32/false
    18794         0f 85/jump-if-!= break/disp32
    18795         # if (name == "<-") break
    18796         (slice-equal? %ecx "<-")  # => eax
    18797         3d/compare-eax-and 0/imm32/false
    18798         0f 85/jump-if-!= break/disp32
    18799         # if slice-starts-with?(name, "*") abort
    18800         8b/-> *ecx 0/r32/eax  # Slice-start
    18801         8a/copy-byte *eax 0/r32/AL
    18802         81 4/subop/and %eax 0xff/imm32
    18803         3d/compare-eax-and 0x2a/imm32/asterisk
    18804         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
    18805         # assert(identifier?(name))
    18806         (identifier? %ecx)  # => eax
    18807         3d/compare-eax-and 0/imm32/false
    18808         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
    18809         #
    18810         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18811         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
    18812         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
    18813         #
    18814         e9/jump loop/disp32
    18815       }
    18816     }
    18817     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18818 $parse-mu-stmt:end:
    18819     # . reclaim locals
    18820     81 0/subop/add %esp 0x10/imm32
    18821     # . restore registers
    18822     5f/pop-to-edi
    18823     5b/pop-to-ebx
    18824     5a/pop-to-edx
    18825     59/pop-to-ecx
    18826     58/pop-to-eax
    18827     # . epilogue
    18828     89/<- %esp 5/r32/ebp
    18829     5d/pop-to-ebp
    18830     c3/return
    18831
    18832 $parse-mu-stmt:abort:
    18833     # error("invalid identifier '" name "'\n")
    18834     (write-buffered *(ebp+0x18) "fn ")
    18835     8b/-> *(ebp+0x10) 0/r32/eax
    18836     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18837     (write-buffered *(ebp+0x18) %eax)
    18838     (write-buffered *(ebp+0x18) ": invalid identifier '")
    18839     (write-slice-buffered *(ebp+0x18) %ecx)
    18840     (write-buffered *(ebp+0x18) "'\n")
    18841     (flush *(ebp+0x18))
    18842     (stop *(ebp+0x1c) 1)
    18843     # never gets here
    18844
    18845 $parse-mu-stmt:error-output-dereferenced:
    18846     # error("invalid identifier '" name "'\n")
    18847     (write-buffered *(ebp+0x18) "fn ")
    18848     8b/-> *(ebp+0x10) 0/r32/eax
    18849     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18850     (write-buffered *(ebp+0x18) %eax)
    18851     (write-buffered *(ebp+0x18) ": output '")
    18852     (write-slice-buffered *(ebp+0x18) %ecx)
    18853     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
    18854     (flush *(ebp+0x18))
    18855     (stop *(ebp+0x1c) 1)
    18856     # never gets here
    18857
    18858 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)
    18859     # pseudocode:
    18860     #   stmt->name = slice-to-string(next-mu-token(line))
    18861     #   while true
    18862     #     name = next-mu-token(line)
    18863     #     v = lookup-var-or-literal(name)
    18864     #     stmt->inouts = append(v, stmt->inouts)
    18865     #
    18866     # . prologue
    18867     55/push-ebp
    18868     89/<- %ebp 4/r32/esp
    18869     # . save registers
    18870     50/push-eax
    18871     51/push-ecx
    18872     52/push-edx
    18873     53/push-ebx
    18874     56/push-esi
    18875     57/push-edi
    18876     # edi = stmt
    18877     8b/-> *(ebp+8) 7/r32/edi
    18878     # var name/ecx: slice
    18879     68/push 0/imm32/end
    18880     68/push 0/imm32/start
    18881     89/<- %ecx 4/r32/esp
    18882     # var is-deref?/edx: boolean = false
    18883     ba/copy-to-edx 0/imm32/false
    18884     # var v/esi: (handle var)
    18885     68/push 0/imm32
    18886     68/push 0/imm32
    18887     89/<- %esi 4/r32/esp
    18888 $add-operation-and-inputs-to-stmt:read-operation:
    18889     (next-mu-token *(ebp+0xc) %ecx)
    18890     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
    18891     (slice-to-string Heap %ecx %eax)
    18892     # var is-get?/ebx: boolean = (name == "get")
    18893     (slice-equal? %ecx "get")  # => eax
    18894     89/<- %ebx 0/r32/eax
    18895     {
    18896 $add-operation-and-inputs-to-stmt:read-inouts:
    18897       # name = next-mu-token(line)
    18898       (next-mu-token *(ebp+0xc) %ecx)
    18899       # if slice-empty?(word-slice) break
    18900       (slice-empty? %ecx)  # => eax
    18901       3d/compare-eax-and 0/imm32/false
    18902       0f 85/jump-if-!= break/disp32
    18903       # if (name == "<-") abort
    18904       (slice-equal? %ecx "<-")
    18905       3d/compare-eax-and 0/imm32/false
    18906       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
    18907       # if (get? && second operand) lookup or create offset
    18908       {
    18909         81 7/subop/compare %ebx 0/imm32/false
    18910         74/jump-if-= break/disp8
    18911         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    18912         3d/compare-eax-and 0/imm32
    18913         74/jump-if-= break/disp8
    18914         (lookup-or-create-constant %eax %ecx %esi)
    18915 #?         (lookup *esi *(esi+4))
    18916 #?         (write-buffered Stderr "creating new output var ")
    18917 #?         (write-int32-hex-buffered Stderr %eax)
    18918 #?         (write-buffered Stderr " for field called ")
    18919 #?         (write-slice-buffered Stderr %ecx)
    18920 #?         (write-buffered Stderr "; var name ")
    18921 #?         (lookup *eax *(eax+4))  # Var-name
    18922 #?         (write-buffered Stderr %eax)
    18923 #?         (write-buffered Stderr Newline)
    18924 #?         (flush Stderr)
    18925         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
    18926       }
    18927       # is-deref? = false
    18928       ba/copy-to-edx 0/imm32/false
    18929       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
    18930       8b/-> *ecx 0/r32/eax  # Slice-start
    18931       8a/copy-byte *eax 0/r32/AL
    18932       81 4/subop/and %eax 0xff/imm32
    18933       3d/compare-eax-and 0x2a/imm32/asterisk
    18934       {
    18935         75/jump-if-!= break/disp8
    18936 $add-operation-and-inputs-to-stmt:inout-is-deref:
    18937         ff 0/subop/increment *ecx
    18938         ba/copy-to-edx 1/imm32/true
    18939       }
    18940       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18941       # if (deref?) some additional checks
    18942       81 7/subop/compare %edx 0/imm32/false
    18943       {
    18944         74/jump-if-= break/disp8
    18945         # if var is not in register, abort
    18946         (lookup *esi *(esi+4))  # => eax
    18947         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    18948         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
    18949         # if var is not an address, abort
    18950         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    18951         (mu-addr-type? %eax)  # => eax
    18952         3d/compare-eax-and 0/imm32/false
    18953         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
    18954       }
    18955 $add-operation-and-inputs-to-stmt:save-var:
    18956       8d/copy-address *(edi+0xc) 0/r32/eax
    18957       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
    18958       #
    18959       e9/jump loop/disp32
    18960     }
    18961 $add-operation-and-inputs-to-stmt:end:
    18962     # . reclaim locals
    18963     81 0/subop/add %esp 0x10/imm32
    18964     # . restore registers
    18965     5f/pop-to-edi
    18966     5e/pop-to-esi
    18967     5b/pop-to-ebx
    18968     5a/pop-to-edx
    18969     59/pop-to-ecx
    18970     58/pop-to-eax
    18971     # . epilogue
    18972     89/<- %esp 5/r32/ebp
    18973     5d/pop-to-ebp
    18974     c3/return
    18975
    18976 $add-operation-and-inputs-to-stmt:abort:
    18977     # error("fn ___: invalid identifier in '" line "'\n")
    18978     (write-buffered *(ebp+0x18) "fn ")
    18979     8b/-> *(ebp+0x14) 0/r32/eax
    18980     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18981     (write-buffered *(ebp+0x18) %eax)
    18982     (rewind-stream *(ebp+0xc))
    18983     (write-buffered *(ebp+0x18) ": invalid identifier in '")
    18984     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    18985     (write-buffered *(ebp+0x18) "'\n")
    18986     (flush *(ebp+0x18))
    18987     (stop *(ebp+0x1c) 1)
    18988     # never gets here
    18989
    18990 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
    18991     # error("fn ___: cannot dereference var ___ on stack\n")
    18992     (write-buffered *(ebp+0x18) "fn ")
    18993     8b/-> *(ebp+0x14) 0/r32/eax
    18994     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18995     (write-buffered *(ebp+0x18) %eax)
    18996     (rewind-stream *(ebp+0xc))
    18997     (write-buffered *(ebp+0x18) ": cannot dereference var '")
    18998     (lookup *esi *(esi+4))  # => eax
    18999     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19000     (write-buffered *(ebp+0x18) %eax)
    19001     (write-buffered *(ebp+0x18) "' on stack\n")
    19002     (flush *(ebp+0x18))
    19003     (stop *(ebp+0x1c) 1)
    19004     # never gets here
    19005
    19006 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
    19007     # error("fn ___: cannot dereference non-addr var ___\n")
    19008     (write-buffered *(ebp+0x18) "fn ")
    19009     8b/-> *(ebp+0x14) 0/r32/eax
    19010     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19011     (write-buffered *(ebp+0x18) %eax)
    19012     (rewind-stream *(ebp+0xc))
    19013     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
    19014     (lookup *esi *(esi+4))  # => eax
    19015     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19016     (write-buffered *(ebp+0x18) %eax)
    19017     (write-buffered *(ebp+0x18) "'\n")
    19018     (flush *(ebp+0x18))
    19019     (stop *(ebp+0x1c) 1)
    19020     # never gets here
    19021
    19022 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
    19023     # . prologue
    19024     55/push-ebp
    19025     89/<- %ebp 4/r32/esp
    19026     # . save registers
    19027     51/push-ecx
    19028     # var word-slice/ecx: slice
    19029     68/push 0/imm32/end
    19030     68/push 0/imm32/start
    19031     89/<- %ecx 4/r32/esp
    19032     # result = false
    19033     b8/copy-to-eax 0/imm32/false
    19034     (rewind-stream *(ebp+8))
    19035     {
    19036       (next-mu-token *(ebp+8) %ecx)
    19037       # if slice-empty?(word-slice) break
    19038       (slice-empty? %ecx)
    19039       3d/compare-eax-and 0/imm32/false
    19040       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19041       0f 85/jump-if-!= break/disp32
    19042       # if slice-starts-with?(word-slice, '#') break
    19043       # . eax = *word-slice->start
    19044       8b/-> *ecx 0/r32/eax
    19045       8a/copy-byte *eax 0/r32/AL
    19046       81 4/subop/and %eax 0xff/imm32
    19047       # . if (eax == '#') break
    19048       3d/compare-eax-and 0x23/imm32/hash
    19049       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19050       0f 84/jump-if-= break/disp32
    19051       # if slice-equal?(word-slice, '<-') return true
    19052       (slice-equal? %ecx "<-")
    19053       3d/compare-eax-and 0/imm32/false
    19054       74/jump-if-= loop/disp8
    19055       b8/copy-to-eax 1/imm32/true
    19056     }
    19057 $stmt-has-outputs:end:
    19058     (rewind-stream *(ebp+8))
    19059     # . reclaim locals
    19060     81 0/subop/add %esp 8/imm32
    19061     # . restore registers
    19062     59/pop-to-ecx
    19063     # . epilogue
    19064     89/<- %esp 5/r32/ebp
    19065     5d/pop-to-ebp
    19066     c3/return
    19067
    19068 # if 'name' starts with a digit, create a new literal var for it
    19069 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
    19070 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)
    19071     # . prologue
    19072     55/push-ebp
    19073     89/<- %ebp 4/r32/esp
    19074     # . save registers
    19075     50/push-eax
    19076     51/push-ecx
    19077     56/push-esi
    19078     # esi = name
    19079     8b/-> *(ebp+8) 6/r32/esi
    19080     # if slice-empty?(name) abort
    19081     (slice-empty? %esi)  # => eax
    19082     3d/compare-eax-and 0/imm32/false
    19083     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
    19084     # var c/ecx: byte = *name->start
    19085     8b/-> *esi 1/r32/ecx
    19086     8a/copy-byte *ecx 1/r32/CL
    19087     81 4/subop/and %ecx 0xff/imm32
    19088     # if (decimal-digit?(c) || c == '-') return new var(name)
    19089     {
    19090       81 7/subop/compare %ecx 0x2d/imm32/dash
    19091       74/jump-if-= $lookup-var-or-literal:literal/disp8
    19092       (decimal-digit? %ecx)  # => eax
    19093       3d/compare-eax-and 0/imm32/false
    19094       74/jump-if-= break/disp8
    19095 $lookup-var-or-literal:literal:
    19096       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19097       eb/jump $lookup-var-or-literal:end/disp8
    19098     }
    19099     # else if (c == '"') return new var(name)
    19100     {
    19101       81 7/subop/compare %ecx 0x22/imm32/dquote
    19102       75/jump-if-!= break/disp8
    19103 $lookup-var-or-literal:literal-string:
    19104       (new-literal-string Heap %esi *(ebp+0x10))
    19105       eb/jump $lookup-var-or-literal:end/disp8
    19106     }
    19107     # otherwise return lookup-var(name, vars)
    19108     {
    19109 $lookup-var-or-literal:var:
    19110       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19111     }
    19112 $lookup-var-or-literal:end:
    19113     # . restore registers
    19114     5e/pop-to-esi
    19115     59/pop-to-ecx
    19116     58/pop-to-eax
    19117     # . epilogue
    19118     89/<- %esp 5/r32/ebp
    19119     5d/pop-to-ebp
    19120     c3/return
    19121
    19122 $lookup-var-or-literal:abort:
    19123     (write-buffered *(ebp+0x18) "fn ")
    19124     8b/-> *(ebp+0x14) 0/r32/eax
    19125     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19126     (write-buffered *(ebp+0x18) %eax)
    19127     (write-buffered *(ebp+0x18) ": empty variable!")
    19128     (flush *(ebp+0x18))
    19129     (stop *(ebp+0x1c) 1)
    19130     # never gets here
    19131
    19132 # return first 'name' from the top (back) of 'vars' and abort if not found
    19133 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)
    19134     # . prologue
    19135     55/push-ebp
    19136     89/<- %ebp 4/r32/esp
    19137     # . save registers
    19138     50/push-eax
    19139     #
    19140     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19141     # if (*out == 0) abort
    19142     8b/-> *(ebp+0x10) 0/r32/eax
    19143     81 7/subop/compare *eax 0/imm32
    19144     74/jump-if-= $lookup-var:abort/disp8
    19145 $lookup-var:end:
    19146     # . restore registers
    19147     58/pop-to-eax
    19148     # . epilogue
    19149     89/<- %esp 5/r32/ebp
    19150     5d/pop-to-ebp
    19151     c3/return
    19152
    19153 $lookup-var:abort:
    19154     (write-buffered *(ebp+0x18) "fn ")
    19155     8b/-> *(ebp+0x14) 0/r32/eax
    19156     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19157     (write-buffered *(ebp+0x18) %eax)
    19158     (write-buffered *(ebp+0x18) ": unknown variable '")
    19159     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19160     (write-buffered *(ebp+0x18) "'\n")
    19161     (flush *(ebp+0x18))
    19162     (stop *(ebp+0x1c) 1)
    19163     # never gets here
    19164
    19165 # return first 'name' from the top (back) of 'vars', and 0/null if not found
    19166 # ensure that 'name' if in a register is the topmost variable in that register
    19167 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)
    19168     # pseudocode:
    19169     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19170     #   var min = vars->data
    19171     #   while curr >= min
    19172     #     var v: (handle var) = *curr
    19173     #     if v->name == name
    19174     #       return
    19175     #     curr -= 12
    19176     #
    19177     # . prologue
    19178     55/push-ebp
    19179     89/<- %ebp 4/r32/esp
    19180     # . save registers
    19181     50/push-eax
    19182     51/push-ecx
    19183     52/push-edx
    19184     53/push-ebx
    19185     56/push-esi
    19186     57/push-edi
    19187     # clear out
    19188     (zero-out *(ebp+0x10) *Handle-size)
    19189     # esi = vars
    19190     8b/-> *(ebp+0xc) 6/r32/esi
    19191     # ebx = vars->top
    19192     8b/-> *esi 3/r32/ebx
    19193     # if (vars->top > vars->size) abort
    19194     3b/compare<- *(esi+4) 0/r32/eax
    19195     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
    19196     # var min/edx: (addr handle var) = vars->data
    19197     8d/copy-address *(esi+8) 2/r32/edx
    19198     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19199     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19200     # var var-in-reg/edi: 16 addrs
    19201     68/push 0/imm32
    19202     68/push 0/imm32
    19203     68/push 0/imm32
    19204     68/push 0/imm32
    19205     68/push 0/imm32
    19206     68/push 0/imm32
    19207     68/push 0/imm32
    19208     68/push 0/imm32
    19209     68/push 0/imm32
    19210     68/push 0/imm32
    19211     68/push 0/imm32
    19212     68/push 0/imm32
    19213     68/push 0/imm32
    19214     68/push 0/imm32
    19215     68/push 0/imm32
    19216     68/push 0/imm32
    19217     89/<- %edi 4/r32/esp
    19218     {
    19219 $lookup-var-helper:loop:
    19220       # if (curr < min) return
    19221       39/compare %ebx 2/r32/edx
    19222       0f 82/jump-if-addr< break/disp32
    19223       # var v/ecx: (addr var) = lookup(*curr)
    19224       (lookup *ebx *(ebx+4))  # => eax
    19225       89/<- %ecx 0/r32/eax
    19226       # var vn/eax: (addr array byte) = lookup(v->name)
    19227       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    19228       # if (vn == name) return curr
    19229       (slice-equal? *(ebp+8) %eax)  # => eax
    19230       3d/compare-eax-and 0/imm32/false
    19231       {
    19232         74/jump-if-= break/disp8
    19233 $lookup-var-helper:found:
    19234         # var vr/eax: (addr array byte) = lookup(v->register)
    19235         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19236         3d/compare-eax-and 0/imm32
    19237         {
    19238           74/jump-if-= break/disp8
    19239 $lookup-var-helper:found-register:
    19240           # var reg/eax: int = get(Registers, vr)
    19241           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19242           8b/-> *eax 0/r32/eax
    19243           # if (var-in-reg[reg]) error
    19244           8b/-> *(edi+eax<<2) 0/r32/eax
    19245           3d/compare-eax-and 0/imm32
    19246           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
    19247         }
    19248 $lookup-var-helper:return:
    19249         # esi = out
    19250         8b/-> *(ebp+0x10) 6/r32/esi
    19251         # *out = *curr
    19252         8b/-> *ebx 0/r32/eax
    19253         89/<- *esi 0/r32/eax
    19254         8b/-> *(ebx+4) 0/r32/eax
    19255         89/<- *(esi+4) 0/r32/eax
    19256         # return
    19257         eb/jump $lookup-var-helper:end/disp8
    19258       }
    19259       # 'name' not yet found; update var-in-reg if v in register
    19260       # . var vr/eax: (addr array byte) = lookup(v->register)
    19261       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19262       # . if (vr == 0) continue
    19263       3d/compare-eax-and 0/imm32
    19264       74/jump-if-= $lookup-var-helper:continue/disp8
    19265       # . var reg/eax: int = get(Registers, vr)
    19266       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19267       8b/-> *eax 0/r32/eax
    19268       # . var-in-reg[reg] = v
    19269       89/<- *(edi+eax<<2) 1/r32/ecx
    19270 $lookup-var-helper:continue:
    19271       # curr -= 12
    19272       81 5/subop/subtract %ebx 0xc/imm32
    19273       e9/jump loop/disp32
    19274     }
    19275 $lookup-var-helper:end:
    19276     # . reclaim locals
    19277     81 0/subop/add %esp 0x40/imm32
    19278     # . restore registers
    19279     5f/pop-to-edi
    19280     5e/pop-to-esi
    19281     5b/pop-to-ebx
    19282     5a/pop-to-edx
    19283     59/pop-to-ecx
    19284     58/pop-to-eax
    19285     # . epilogue
    19286     89/<- %esp 5/r32/ebp
    19287     5d/pop-to-ebp
    19288     c3/return
    19289
    19290 $lookup-var-helper:error1:
    19291     (write-buffered *(ebp+0x18) "fn ")
    19292     8b/-> *(ebp+0x14) 0/r32/eax
    19293     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19294     (write-buffered *(ebp+0x18) %eax)
    19295     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
    19296     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19297     (write-buffered *(ebp+0x18) "'\n")
    19298     (flush *(ebp+0x18))
    19299     (stop *(ebp+0x1c) 1)
    19300     # never gets here
    19301
    19302 $lookup-var-helper:error2:
    19303     # eax contains the conflicting var at this point
    19304     (write-buffered *(ebp+0x18) "fn ")
    19305     50/push-eax
    19306     8b/-> *(ebp+0x14) 0/r32/eax
    19307     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19308     (write-buffered *(ebp+0x18) %eax)
    19309     58/pop-eax
    19310     (write-buffered *(ebp+0x18) ": register ")
    19311     50/push-eax
    19312     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    19313     (write-buffered *(ebp+0x18) %eax)
    19314     58/pop-to-eax
    19315     (write-buffered *(ebp+0x18) " reads var '")
    19316     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19317     (write-buffered *(ebp+0x18) "' after writing var '")
    19318     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19319     (write-buffered *(ebp+0x18) %eax)
    19320     (write-buffered *(ebp+0x18) "'\n")
    19321     (flush *(ebp+0x18))
    19322     (stop *(ebp+0x1c) 1)
    19323     # never gets here
    19324
    19325 dump-vars:  # vars: (addr stack live-var)
    19326     # pseudocode:
    19327     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19328     #   var min = vars->data
    19329     #   while curr >= min
    19330     #     var v: (handle var) = *curr
    19331     #     print v
    19332     #     curr -= 12
    19333     #
    19334     # . prologue
    19335     55/push-ebp
    19336     89/<- %ebp 4/r32/esp
    19337     # . save registers
    19338     52/push-edx
    19339     53/push-ebx
    19340     56/push-esi
    19341     # esi = vars
    19342     8b/-> *(ebp+8) 6/r32/esi
    19343     # ebx = vars->top
    19344     8b/-> *esi 3/r32/ebx
    19345     # var min/edx: (addr handle var) = vars->data
    19346     8d/copy-address *(esi+8) 2/r32/edx
    19347     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19348     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19349     {
    19350 $dump-vars:loop:
    19351       # if (curr < min) return
    19352       39/compare %ebx 2/r32/edx
    19353       0f 82/jump-if-addr< break/disp32
    19354       #
    19355       (write-buffered Stderr "  var@")
    19356       (dump-var 2 %ebx)
    19357       # curr -= 12
    19358       81 5/subop/subtract %ebx 0xc/imm32
    19359       e9/jump loop/disp32
    19360     }
    19361 $dump-vars:end:
    19362     # . restore registers
    19363     5e/pop-to-esi
    19364     5b/pop-to-ebx
    19365     5a/pop-to-edx
    19366     # . epilogue
    19367     89/<- %esp 5/r32/ebp
    19368     5d/pop-to-ebp
    19369     c3/return
    19370
    19371 == data
    19372 # Like Registers, but no esp or ebp
    19373 Mu-registers:  # (addr stream {(handle array byte), int})
    19374   # a table is a stream
    19375   0xa8/imm32/write
    19376   0/imm32/read
    19377   0xa8/imm32/length
    19378   # data
    19379   # general-purpose registers
    19380   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
    19381   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19382   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19383   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19384   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19385   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19386   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19387   # floating-point registers
    19388   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
    19389   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
    19390   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
    19391   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
    19392   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
    19393   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
    19394   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
    19395   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
    19396
    19397 # Like Mu-registers, but with unique codes for integer and floating-point
    19398 # registers.
    19399 # Don't use this for code-generation, only for checking.
    19400 Mu-registers-unique:  # (addr stream {(handle array byte), int})
    19401   # a table is a stream
    19402   0xa8/imm32/write
    19403   0/imm32/read
    19404   0xa8/imm32/length
    19405   # data
    19406   # general-purpose registers
    19407   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19408   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19409   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19410   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19411   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19412   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19413   # floating-point registers
    19414   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
    19415   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
    19416   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
    19417   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
    19418   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
    19419   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
    19420   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
    19421   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
    19422
    19423 $Mu-register-eax:
    19424   0x11/imm32/alloc-id
    19425   3/imm32/size
    19426   0x65/e 0x61/a 0x78/x
    19427
    19428 $Mu-register-ecx:
    19429   0x11/imm32/alloc-id
    19430   3/imm32/size
    19431   0x65/e 0x63/c 0x78/x
    19432
    19433 $Mu-register-edx:
    19434   0x11/imm32/alloc-id
    19435   3/imm32/size
    19436   0x65/e 0x64/d 0x78/x
    19437
    19438 $Mu-register-ebx:
    19439   0x11/imm32/alloc-id
    19440   3/imm32/size
    19441   0x65/e 0x62/b 0x78/x
    19442
    19443 $Mu-register-esi:
    19444   0x11/imm32/alloc-id
    19445   3/imm32/size
    19446   0x65/e 0x73/s 0x69/i
    19447
    19448 $Mu-register-edi:
    19449   0x11/imm32/alloc-id
    19450   3/imm32/size
    19451   0x65/e 0x64/d 0x69/i
    19452
    19453 $Mu-register-xmm0:
    19454   0x11/imm32/alloc-id:fake:payload
    19455   # "xmm0"
    19456   0x4/imm32/size
    19457   0x78/x 0x6d/m 0x6d/m 0x30/0
    19458
    19459 $Mu-register-xmm1:
    19460   0x11/imm32/alloc-id:fake:payload
    19461   # "xmm1"
    19462   0x4/imm32/size
    19463   0x78/x 0x6d/m 0x6d/m 0x31/1
    19464
    19465 $Mu-register-xmm2:
    19466   0x11/imm32/alloc-id:fake:payload
    19467   # "xmm2"
    19468   0x4/imm32/size
    19469   0x78/x 0x6d/m 0x6d/m 0x32/2
    19470
    19471 $Mu-register-xmm3:
    19472   0x11/imm32/alloc-id:fake:payload
    19473   # "xmm3"
    19474   0x4/imm32/size
    19475   0x78/x 0x6d/m 0x6d/m 0x33/3
    19476
    19477 $Mu-register-xmm4:
    19478   0x11/imm32/alloc-id:fake:payload
    19479   # "xmm4"
    19480   0x4/imm32/size
    19481   0x78/x 0x6d/m 0x6d/m 0x34/4
    19482
    19483 $Mu-register-xmm5:
    19484   0x11/imm32/alloc-id:fake:payload
    19485   # "xmm5"
    19486   0x4/imm32/size
    19487   0x78/x 0x6d/m 0x6d/m 0x35/5
    19488
    19489 $Mu-register-xmm6:
    19490   0x11/imm32/alloc-id:fake:payload
    19491   # "xmm6"
    19492   0x4/imm32/size
    19493   0x78/x 0x6d/m 0x6d/m 0x36/6
    19494
    19495 $Mu-register-xmm7:
    19496   0x11/imm32/alloc-id:fake:payload
    19497   # "xmm7"
    19498   0x4/imm32/size
    19499   0x78/x 0x6d/m 0x6d/m 0x37/7
    19500
    19501 == code
    19502
    19503 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
    19504 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
    19505     # . prologue
    19506     55/push-ebp
    19507     89/<- %ebp 4/r32/esp
    19508     # . save registers
    19509     50/push-eax
    19510     # var out-addr/eax: (addr var)
    19511     (lookup *(ebp+8) *(ebp+0xc))  # => eax
    19512     #
    19513     (binding-exists? %eax *(ebp+0x10))  # => eax
    19514     3d/compare-eax-and 0/imm32/false
    19515     75/jump-if-!= $maybe-define-var:end/disp8
    19516     # otherwise update vars
    19517     (push *(ebp+0x10) *(ebp+8))
    19518     (push *(ebp+0x10) *(ebp+0xc))
    19519     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
    19520 $maybe-define-var:end:
    19521     # . restore registers
    19522     58/pop-to-eax
    19523     # . epilogue
    19524     89/<- %esp 5/r32/ebp
    19525     5d/pop-to-ebp
    19526     c3/return
    19527
    19528 # simpler version of lookup-var-helper
    19529 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    19530     # pseudocode:
    19531     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19532     #   var min = vars->data
    19533     #   while curr >= min
    19534     #     var v: (handle var) = *curr
    19535     #     if v->name == target->name
    19536     #       return true
    19537     #     curr -= 12
    19538     #   return false
    19539     #
    19540     # . prologue
    19541     55/push-ebp
    19542     89/<- %ebp 4/r32/esp
    19543     # . save registers
    19544     51/push-ecx
    19545     52/push-edx
    19546     56/push-esi
    19547     # var target-name/ecx: (addr array byte) = lookup(target->name)
    19548     8b/-> *(ebp+8) 0/r32/eax
    19549     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19550     89/<- %ecx 0/r32/eax
    19551     # esi = vars
    19552     8b/-> *(ebp+0xc) 6/r32/esi
    19553     # eax = vars->top
    19554     8b/-> *esi 0/r32/eax
    19555     # var min/edx: (addr handle var) = vars->data
    19556     8d/copy-address *(esi+8) 2/r32/edx
    19557     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    19558     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
    19559     {
    19560 $binding-exists?:loop:
    19561       # if (curr < min) return
    19562       39/compare %esi 2/r32/edx
    19563       0f 82/jump-if-addr< break/disp32
    19564       # var v/eax: (addr var) = lookup(*curr)
    19565       (lookup *esi *(esi+4))  # => eax
    19566       # var vn/eax: (addr array byte) = lookup(v->name)
    19567       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19568       # if (vn == target-name) return true
    19569       (string-equal? %ecx %eax)  # => eax
    19570       3d/compare-eax-and 0/imm32/false
    19571       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
    19572       # curr -= 12
    19573       81 5/subop/subtract %esi 0xc/imm32
    19574       e9/jump loop/disp32
    19575     }
    19576     b8/copy-to-eax 0/imm32/false
    19577 $binding-exists?:end:
    19578     # . restore registers
    19579     5e/pop-to-esi
    19580     5a/pop-to-edx
    19581     59/pop-to-ecx
    19582     # . epilogue
    19583     89/<- %esp 5/r32/ebp
    19584     5d/pop-to-ebp
    19585     c3/return
    19586
    19587 test-parse-mu-stmt:
    19588     # . prologue
    19589     55/push-ebp
    19590     89/<- %ebp 4/r32/esp
    19591     # setup
    19592     8b/-> *Primitive-type-ids 0/r32/eax
    19593     89/<- *Type-id 0/r32/eax  # stream-write
    19594     (clear-stream _test-input-stream)
    19595     (write _test-input-stream "increment n\n")
    19596     # var vars/ecx: (stack (addr var) 16)
    19597     81 5/subop/subtract %esp 0xc0/imm32
    19598     68/push 0xc0/imm32/size
    19599     68/push 0/imm32/top
    19600     89/<- %ecx 4/r32/esp
    19601     (clear-stack %ecx)
    19602     # var v/edx: (handle var)
    19603     68/push 0/imm32
    19604     68/push 0/imm32
    19605     89/<- %edx 4/r32/esp
    19606     # var s/eax: (handle array byte)
    19607     68/push 0/imm32
    19608     68/push 0/imm32
    19609     89/<- %eax 4/r32/esp
    19610     # v = new var("n")
    19611     (copy-array Heap "n" %eax)
    19612     (new-var Heap *eax *(eax+4) %edx)
    19613     #
    19614     (push %ecx *edx)
    19615     (push %ecx *(edx+4))
    19616     (push %ecx 0)
    19617     # var out/eax: (handle stmt)
    19618     68/push 0/imm32
    19619     68/push 0/imm32
    19620     89/<- %eax 4/r32/esp
    19621     # convert
    19622     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19623     # var out-addr/edx: (addr stmt) = lookup(*out)
    19624     (lookup *eax *(eax+4))  # => eax
    19625     89/<- %edx 0/r32/eax
    19626     # out->tag
    19627     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
    19628     # out->operation
    19629     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19630     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
    19631     # out->inouts->value->name
    19632     # . eax = out->inouts
    19633     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19634     # . eax = out->inouts->value
    19635     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19636     # . eax = out->inouts->value->name
    19637     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19638     # .
    19639     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
    19640     # . epilogue
    19641     89/<- %esp 5/r32/ebp
    19642     5d/pop-to-ebp
    19643     c3/return
    19644
    19645 test-parse-mu-stmt-with-comma:
    19646     # . prologue
    19647     55/push-ebp
    19648     89/<- %ebp 4/r32/esp
    19649     # setup
    19650     8b/-> *Primitive-type-ids 0/r32/eax
    19651     89/<- *Type-id 0/r32/eax  # stream-write
    19652     (clear-stream _test-input-stream)
    19653     (write _test-input-stream "copy-to n, 3\n")
    19654     # var vars/ecx: (stack (addr var) 16)
    19655     81 5/subop/subtract %esp 0xc0/imm32
    19656     68/push 0xc0/imm32/size
    19657     68/push 0/imm32/top
    19658     89/<- %ecx 4/r32/esp
    19659     (clear-stack %ecx)
    19660     # var v/edx: (handle var)
    19661     68/push 0/imm32
    19662     68/push 0/imm32
    19663     89/<- %edx 4/r32/esp
    19664     # var s/eax: (handle array byte)
    19665     68/push 0/imm32
    19666     68/push 0/imm32
    19667     89/<- %eax 4/r32/esp
    19668     # v = new var("n")
    19669     (copy-array Heap "n" %eax)
    19670     (new-var Heap *eax *(eax+4) %edx)
    19671     #
    19672     (push %ecx *edx)
    19673     (push %ecx *(edx+4))
    19674     (push %ecx 0)
    19675     # var out/eax: (handle stmt)
    19676     68/push 0/imm32
    19677     68/push 0/imm32
    19678     89/<- %eax 4/r32/esp
    19679     # convert
    19680     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19681     # var out-addr/edx: (addr stmt) = lookup(*out)
    19682     (lookup *eax *(eax+4))  # => eax
    19683     89/<- %edx 0/r32/eax
    19684     # out->tag
    19685     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
    19686     # out->operation
    19687     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19688     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
    19689     # out->inouts->value->name
    19690     # . eax = out->inouts
    19691     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19692     # . eax = out->inouts->value
    19693     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19694     # . eax = out->inouts->value->name
    19695     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19696     # .
    19697     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
    19698     # . epilogue
    19699     89/<- %esp 5/r32/ebp
    19700     5d/pop-to-ebp
    19701     c3/return
    19702
    19703 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
    19704     # . prologue
    19705     55/push-ebp
    19706     89/<- %ebp 4/r32/esp
    19707     # . save registers
    19708     50/push-eax
    19709     51/push-ecx
    19710     # ecx = out
    19711     8b/-> *(ebp+0x14) 1/r32/ecx
    19712     #
    19713     (allocate *(ebp+8) *Var-size %ecx)
    19714     # var out-addr/eax: (addr var)
    19715     (lookup *ecx *(ecx+4))  # => eax
    19716     # out-addr->name = name
    19717     8b/-> *(ebp+0xc) 1/r32/ecx
    19718     89/<- *eax 1/r32/ecx  # Var-name
    19719     8b/-> *(ebp+0x10) 1/r32/ecx
    19720     89/<- *(eax+4) 1/r32/ecx  # Var-name
    19721 #?     (write-buffered Stderr "var ")
    19722 #?     (lookup *(ebp+0xc) *(ebp+0x10))
    19723 #?     (write-buffered Stderr %eax)
    19724 #?     (write-buffered Stderr " at ")
    19725 #?     8b/-> *(ebp+0x14) 1/r32/ecx
    19726 #?     (lookup *ecx *(ecx+4))  # => eax
    19727 #?     (write-int32-hex-buffered Stderr %eax)
    19728 #?     (write-buffered Stderr Newline)
    19729 #?     (flush Stderr)
    19730 $new-var:end:
    19731     # . restore registers
    19732     59/pop-to-ecx
    19733     58/pop-to-eax
    19734     # . epilogue
    19735     89/<- %esp 5/r32/ebp
    19736     5d/pop-to-ebp
    19737     c3/return
    19738
    19739 # WARNING: modifies name
    19740 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)
    19741     # . prologue
    19742     55/push-ebp
    19743     89/<- %ebp 4/r32/esp
    19744     # . save registers
    19745     50/push-eax
    19746     51/push-ecx
    19747     # first strip out metadata
    19748     8b/-> *(ebp+0xc) 1/r32/ecx
    19749     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
    19750     # if (!is-hex-int?(name)) abort
    19751     (hex-int? *(ebp+0xc))  # => eax
    19752     3d/compare-eax-and 0/imm32/false
    19753     0f 84/jump-if-= $new-literal-integer:abort/disp32
    19754     # a little more error-checking
    19755     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    19756     # out = new var(s)
    19757     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    19758     # var out-addr/ecx: (addr var) = lookup(*out)
    19759     8b/-> *(ebp+0x10) 0/r32/eax
    19760     (lookup *eax *(eax+4))  # => eax
    19761     89/<- %ecx 0/r32/eax
    19762     # out-addr->block-depth = *Curr-block-depth
    19763     8b/-> *Curr-block-depth 0/r32/eax
    19764     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19765     # out-addr->type = new tree()
    19766     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19767     (allocate *(ebp+8) *Type-tree-size %eax)
    19768     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19769     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19770     # nothing else to do; default type is 'literal'
    19771 $new-literal-integer:end:
    19772     # . reclaim locals
    19773     81 0/subop/add %esp 8/imm32
    19774     # . restore registers
    19775     59/pop-to-ecx
    19776     58/pop-to-eax
    19777     # . epilogue
    19778     89/<- %esp 5/r32/ebp
    19779     5d/pop-to-ebp
    19780     c3/return
    19781
    19782 $new-literal-integer:abort:
    19783     (write-buffered *(ebp+0x18) "fn ")
    19784     8b/-> *(ebp+0x14) 0/r32/eax
    19785     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19786     (write-buffered *(ebp+0x18) %eax)
    19787     (write-buffered *(ebp+0x18) ": variable '")
    19788     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
    19789     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
    19790     (flush *(ebp+0x18))
    19791     (stop *(ebp+0x1c) 1)
    19792     # never gets here
    19793
    19794 # precondition: name is a valid hex integer; require a '0x' prefix
    19795 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
    19796     # . prologue
    19797     55/push-ebp
    19798     89/<- %ebp 4/r32/esp
    19799     # . save registers
    19800     50/push-eax
    19801     51/push-ecx
    19802     52/push-edx
    19803     # ecx = name
    19804     8b/-> *(ebp+8) 1/r32/ecx
    19805     # var start/edx: (addr byte) = name->start
    19806     8b/-> *ecx 2/r32/edx
    19807     # if (*start == '-') ++start
    19808     b8/copy-to-eax 0/imm32
    19809     8a/copy-byte *edx 0/r32/AL
    19810     3d/compare-eax-and 0x2d/imm32/dash
    19811     {
    19812       75/jump-if-!= break/disp8
    19813       42/increment-edx
    19814     }
    19815     # var end/ecx: (addr byte) = name->end
    19816     8b/-> *(ecx+4) 1/r32/ecx
    19817     # var len/eax: int = name->end - name->start
    19818     89/<- %eax 1/r32/ecx
    19819     29/subtract-from %eax 2/r32/edx
    19820     # if (len <= 1) return
    19821     3d/compare-eax-with 1/imm32
    19822     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
    19823 $check-mu-hex-int:length->-1:
    19824     # if slice-starts-with?({start, end}, "0x") return
    19825     # . var tmp = {start, end}
    19826     51/push-ecx
    19827     52/push-edx
    19828     89/<- %eax 4/r32/esp
    19829     # .
    19830     (slice-starts-with? %eax "0x")  # => eax
    19831     # . reclaim tmp
    19832     81 0/subop/add %esp 8/imm32
    19833     # .
    19834     3d/compare-eax-with 0/imm32/false
    19835     75/jump-if-!= $check-mu-hex-int:end/disp8
    19836 $check-mu-hex-int:abort:
    19837     # otherwise abort
    19838     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
    19839     (write-slice-buffered *(ebp+0xc) *(ebp+8))
    19840     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
    19841     (flush *(ebp+0xc))
    19842     (stop *(ebp+0x10) 1)
    19843 $check-mu-hex-int:end:
    19844     # . restore registers
    19845     5a/pop-to-edx
    19846     59/pop-to-ecx
    19847     58/pop-to-eax
    19848     # . epilogue
    19849     89/<- %esp 5/r32/ebp
    19850     5d/pop-to-ebp
    19851     c3/return
    19852
    19853 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19854     # . prologue
    19855     55/push-ebp
    19856     89/<- %ebp 4/r32/esp
    19857     # . save registers
    19858     50/push-eax
    19859     51/push-ecx
    19860     # var s/ecx: (handle array byte)
    19861     68/push 0/imm32
    19862     68/push 0/imm32
    19863     89/<- %ecx 4/r32/esp
    19864     # s = slice-to-string(name)
    19865     (slice-to-string Heap *(ebp+0xc) %ecx)
    19866     # allocate to out
    19867     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19868     # var out-addr/ecx: (addr var) = lookup(*out)
    19869     8b/-> *(ebp+0x10) 1/r32/ecx
    19870     (lookup *ecx *(ecx+4))  # => eax
    19871     89/<- %ecx 0/r32/eax
    19872     # out-addr->block-depth = *Curr-block-depth
    19873     8b/-> *Curr-block-depth 0/r32/eax
    19874     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19875     # out-addr->type/eax = new type
    19876     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19877     (allocate *(ebp+8) *Type-tree-size %eax)
    19878     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19879     # nothing else to do; default type is 'literal'
    19880     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19881 $new-literal:end:
    19882     # . reclaim locals
    19883     81 0/subop/add %esp 8/imm32
    19884     # . restore registers
    19885     59/pop-to-ecx
    19886     58/pop-to-eax
    19887     # . epilogue
    19888     89/<- %esp 5/r32/ebp
    19889     5d/pop-to-ebp
    19890     c3/return
    19891
    19892 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19893     # . prologue
    19894     55/push-ebp
    19895     89/<- %ebp 4/r32/esp
    19896     # . save registers
    19897     50/push-eax
    19898     51/push-ecx
    19899     # var s/ecx: (handle array byte)
    19900     68/push 0/imm32
    19901     68/push 0/imm32
    19902     89/<- %ecx 4/r32/esp
    19903     # s = slice-to-string(name)
    19904     (slice-to-string Heap *(ebp+0xc) %ecx)
    19905     # allocate to out
    19906     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19907     # var out-addr/ecx: (addr var) = lookup(*out)
    19908     8b/-> *(ebp+0x10) 1/r32/ecx
    19909     (lookup *ecx *(ecx+4))  # => eax
    19910     89/<- %ecx 0/r32/eax
    19911     # out-addr->block-depth = *Curr-block-depth
    19912     8b/-> *Curr-block-depth 0/r32/eax
    19913     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19914     # out-addr->type/eax = new type
    19915     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19916     (allocate *(ebp+8) *Type-tree-size %eax)
    19917     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19918     # out-addr->type->value = literal-string
    19919     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
    19920     # out-addr->type->is-atom? = true
    19921     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19922 $new-literal-string:end:
    19923     # . reclaim locals
    19924     81 0/subop/add %esp 8/imm32
    19925     # . restore registers
    19926     59/pop-to-ecx
    19927     58/pop-to-eax
    19928     # . epilogue
    19929     89/<- %esp 5/r32/ebp
    19930     5d/pop-to-ebp
    19931     c3/return
    19932
    19933 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19934     # . prologue
    19935     55/push-ebp
    19936     89/<- %ebp 4/r32/esp
    19937     # . save registers
    19938     51/push-ecx
    19939     # var tmp/ecx: (handle array byte)
    19940     68/push 0/imm32
    19941     68/push 0/imm32
    19942     89/<- %ecx 4/r32/esp
    19943     # tmp = slice-to-string(name)
    19944     (slice-to-string Heap *(ebp+0xc) %ecx)
    19945     # out = new-var(tmp)
    19946     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19947 $new-var-from-slice:end:
    19948     # . reclaim locals
    19949     81 0/subop/add %esp 8/imm32
    19950     # . restore registers
    19951     59/pop-to-ecx
    19952     # . epilogue
    19953     89/<- %esp 5/r32/ebp
    19954     5d/pop-to-ebp
    19955     c3/return
    19956
    19957 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    19958     # . prologue
    19959     55/push-ebp
    19960     89/<- %ebp 4/r32/esp
    19961     # . save registers
    19962     50/push-eax
    19963     51/push-ecx
    19964     #
    19965     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
    19966     # var out-addr/eax: (addr stmt) = lookup(*out)
    19967     8b/-> *(ebp+0x14) 0/r32/eax
    19968     (lookup *eax *(eax+4))  # => eax
    19969     # out-addr->tag = stmt
    19970     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
    19971     # result->var = var
    19972     8b/-> *(ebp+0xc) 1/r32/ecx
    19973     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
    19974     8b/-> *(ebp+0x10) 1/r32/ecx
    19975     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
    19976 $new-var-def:end:
    19977     # . restore registers
    19978     59/pop-to-ecx
    19979     58/pop-to-eax
    19980     # . epilogue
    19981     89/<- %esp 5/r32/ebp
    19982     5d/pop-to-ebp
    19983     c3/return
    19984
    19985 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    19986     # . prologue
    19987     55/push-ebp
    19988     89/<- %ebp 4/r32/esp
    19989     # . save registers
    19990     50/push-eax
    19991     # eax = out
    19992     8b/-> *(ebp+0x14) 0/r32/eax
    19993     #
    19994     (allocate *(ebp+8) *Stmt-size %eax)
    19995     # var out-addr/eax: (addr stmt) = lookup(*out)
    19996     (lookup *eax *(eax+4))  # => eax
    19997     # set tag
    19998     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
    19999     # set output
    20000     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
    20001     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
    20002 $new-reg-var-def:end:
    20003     # . restore registers
    20004     58/pop-to-eax
    20005     # . epilogue
    20006     89/<- %esp 5/r32/ebp
    20007     5d/pop-to-ebp
    20008     c3/return
    20009
    20010 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
    20011     # . prologue
    20012     55/push-ebp
    20013     89/<- %ebp 4/r32/esp
    20014     # . save registers
    20015     50/push-eax
    20016     51/push-ecx
    20017     57/push-edi
    20018     # edi = out
    20019     8b/-> *(ebp+0x1c) 7/r32/edi
    20020     # *out = new list
    20021     (allocate *(ebp+8) *List-size %edi)
    20022     # var out-addr/edi: (addr list _type) = lookup(*out)
    20023     (lookup *edi *(edi+4))  # => eax
    20024     89/<- %edi 0/r32/eax
    20025     # out-addr->value = value
    20026     8b/-> *(ebp+0xc) 0/r32/eax
    20027     89/<- *edi 0/r32/eax  # List-value
    20028     8b/-> *(ebp+0x10) 0/r32/eax
    20029     89/<- *(edi+4) 0/r32/eax  # List-value
    20030     # if (list == null) return
    20031     81 7/subop/compare *(ebp+0x14) 0/imm32
    20032     74/jump-if-= $append-list:end/disp8
    20033     # otherwise append
    20034 $append-list:non-empty-list:
    20035     # var curr/eax: (addr list _type) = lookup(list)
    20036     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20037     # while (curr->next != null) curr = curr->next
    20038     {
    20039       81 7/subop/compare *(eax+8) 0/imm32  # List-next
    20040       74/jump-if-= break/disp8
    20041       # curr = lookup(curr->next)
    20042       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
    20043       #
    20044       eb/jump loop/disp8
    20045     }
    20046     # edi = out
    20047     8b/-> *(ebp+0x1c) 7/r32/edi
    20048     # curr->next = out
    20049     8b/-> *edi 1/r32/ecx
    20050     89/<- *(eax+8) 1/r32/ecx  # List-next
    20051     8b/-> *(edi+4) 1/r32/ecx
    20052     89/<- *(eax+0xc) 1/r32/ecx  # List-next
    20053     # out = list
    20054     8b/-> *(ebp+0x14) 1/r32/ecx
    20055     89/<- *edi 1/r32/ecx
    20056     8b/-> *(ebp+0x18) 1/r32/ecx
    20057     89/<- *(edi+4) 1/r32/ecx
    20058 $append-list:end:
    20059     # . restore registers
    20060     5f/pop-to-edi
    20061     59/pop-to-ecx
    20062     58/pop-to-eax
    20063     # . epilogue
    20064     89/<- %esp 5/r32/ebp
    20065     5d/pop-to-ebp
    20066     c3/return
    20067
    20068 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
    20069     # . prologue
    20070     55/push-ebp
    20071     89/<- %ebp 4/r32/esp
    20072     # . save registers
    20073     50/push-eax
    20074     51/push-ecx
    20075     57/push-edi
    20076     # edi = out
    20077     8b/-> *(ebp+0x20) 7/r32/edi
    20078     # out = new stmt-var
    20079     (allocate *(ebp+8) *Stmt-var-size %edi)
    20080     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
    20081     (lookup *edi *(edi+4))  # => eax
    20082     89/<- %ecx 0/r32/eax
    20083     # out-addr->value = v
    20084     8b/-> *(ebp+0xc) 0/r32/eax
    20085     89/<- *ecx 0/r32/eax  # Stmt-var-value
    20086     8b/-> *(ebp+0x10) 0/r32/eax
    20087     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
    20088     # out-addr->is-deref? = is-deref?
    20089     8b/-> *(ebp+0x1c) 0/r32/eax
    20090     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
    20091     # if (vars == null) return result
    20092     81 7/subop/compare *(ebp+0x14) 0/imm32/null
    20093     74/jump-if-= $append-stmt-var:end/disp8
    20094     # otherwise append
    20095     # var curr/eax: (addr stmt-var) = lookup(vars)
    20096     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20097     # while (curr->next != null) curr = curr->next
    20098     {
    20099       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    20100       74/jump-if-= break/disp8
    20101       # curr = lookup(curr->next)
    20102       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
    20103       #
    20104       eb/jump loop/disp8
    20105     }
    20106     # curr->next = out
    20107     8b/-> *edi 1/r32/ecx
    20108     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
    20109     8b/-> *(edi+4) 1/r32/ecx
    20110     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
    20111     # out = vars
    20112     8b/-> *(ebp+0x14) 1/r32/ecx
    20113     89/<- *edi 1/r32/ecx
    20114     8b/-> *(ebp+0x18) 1/r32/ecx
    20115     89/<- *(edi+4) 1/r32/ecx
    20116 $append-stmt-var:end:
    20117     # . restore registers
    20118     5f/pop-to-edi
    20119     59/pop-to-ecx
    20120     58/pop-to-eax
    20121     # . epilogue
    20122     89/<- %esp 5/r32/ebp
    20123     5d/pop-to-ebp
    20124     c3/return
    20125
    20126 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
    20127     # . prologue
    20128     55/push-ebp
    20129     89/<- %ebp 4/r32/esp
    20130     # . save registers
    20131     50/push-eax
    20132     56/push-esi
    20133     # esi = block
    20134     8b/-> *(ebp+0xc) 6/r32/esi
    20135     # block->stmts = append(x, block->stmts)
    20136     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
    20137     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
    20138 $append-to-block:end:
    20139     # . restore registers
    20140     5e/pop-to-esi
    20141     58/pop-to-eax
    20142     # . epilogue
    20143     89/<- %esp 5/r32/ebp
    20144     5d/pop-to-ebp
    20145     c3/return
    20146
    20147 ## Parsing types
    20148 # We need to create metadata on user-defined types, and we need to use this
    20149 # metadata as we parse instructions.
    20150 # However, we also want to allow types to be used before their definitions.
    20151 # This means we can't ever assume any type data structures exist.
    20152
    20153 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
    20154     # . prologue
    20155     55/push-ebp
    20156     89/<- %ebp 4/r32/esp
    20157     # . save registers
    20158     50/push-eax
    20159     56/push-esi
    20160     # var container-type/esi: type-id
    20161     (container-type *(ebp+8))  # => eax
    20162     89/<- %esi 0/r32/eax
    20163     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
    20164     68/push 0/imm32
    20165     68/push 0/imm32
    20166     89/<- %eax 4/r32/esp
    20167     (find-or-create-typeinfo %esi %eax)
    20168     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
    20169     (lookup *eax *(eax+4))  # => eax
    20170     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
    20171 #?     (write-buffered Stderr "constant: ")
    20172 #?     (write-slice-buffered Stderr *(ebp+0xc))
    20173 #?     (write-buffered Stderr Newline)
    20174 #?     (flush Stderr)
    20175     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
    20176 #?     8b/-> *(ebp+0x10) 0/r32/eax
    20177 #?     (write-buffered Stderr "@")
    20178 #?     (lookup *eax *(eax+4))
    20179 #?     (write-int32-hex-buffered Stderr %eax)
    20180 #?     (lookup *eax *(eax+4))
    20181 #?     (write-buffered Stderr %eax)
    20182 #?     (write-buffered Stderr Newline)
    20183 #?     (flush Stderr)
    20184 #?     (write-buffered Stderr "offset: ")
    20185 #?     8b/-> *(eax+0x14) 0/r32/eax
    20186 #?     (write-int32-hex-buffered Stderr %eax)
    20187 #?     (write-buffered Stderr Newline)
    20188 #?     (flush Stderr)
    20189 $lookup-or-create-constant:end:
    20190     # . reclaim locals
    20191     81 0/subop/add %esp 8/imm32
    20192     # . restore registers
    20193     5e/pop-to-esi
    20194     58/pop-to-eax
    20195     # . epilogue
    20196     89/<- %esp 5/r32/ebp
    20197     5d/pop-to-ebp
    20198     c3/return
    20199
    20200 # if addr var:
    20201 #   container->var->type->right->left->value
    20202 # otherwise
    20203 #   container->var->type->value
    20204 container-type:  # container: (addr stmt-var) -> result/eax: type-id
    20205     # . prologue
    20206     55/push-ebp
    20207     89/<- %ebp 4/r32/esp
    20208     #
    20209     8b/-> *(ebp+8) 0/r32/eax
    20210     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    20211     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20212     {
    20213       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
    20214       74/jump-if-= break/disp8
    20215       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    20216       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    20217     }
    20218     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    20219 $container-type:end:
    20220     # . epilogue
    20221     89/<- %esp 5/r32/ebp
    20222     5d/pop-to-ebp
    20223     c3/return
    20224
    20225 container?:  # t: type-id -> result/eax: boolean
    20226     # . prologue
    20227     55/push-ebp
    20228     89/<- %ebp 4/r32/esp
    20229     #
    20230     8b/-> *(ebp+8) 0/r32/eax
    20231     c1/shift 4/subop/left %eax 2/imm8
    20232     3b/compare 0/r32/eax *Primitive-type-ids
    20233     0f 9d/set-if->= %al
    20234     81 4/subop/and %eax 0xff/imm32
    20235 $container?:end:
    20236     # . epilogue
    20237     89/<- %esp 5/r32/ebp
    20238     5d/pop-to-ebp
    20239     c3/return
    20240
    20241 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20242     # . prologue
    20243     55/push-ebp
    20244     89/<- %ebp 4/r32/esp
    20245     # . save registers
    20246     50/push-eax
    20247     51/push-ecx
    20248     52/push-edx
    20249     57/push-edi
    20250     # edi = out
    20251     8b/-> *(ebp+0xc) 7/r32/edi
    20252     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
    20253     68/push 0/imm32
    20254     68/push 0/imm32
    20255     89/<- %ecx 4/r32/esp
    20256     # find-typeinfo(t, out)
    20257     (find-typeinfo *(ebp+8) %edi)
    20258     {
    20259       # if (*out != 0) break
    20260       81 7/subop/compare *edi 0/imm32
    20261       0f 85/jump-if-!= break/disp32
    20262 $find-or-create-typeinfo:create:
    20263       # *out = allocate
    20264       (allocate Heap *Typeinfo-size %edi)
    20265       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20266       (lookup *edi *(edi+4))  # => eax
    20267 #?     (write-buffered Stderr "created typeinfo at ")
    20268 #?     (write-int32-hex-buffered Stderr %eax)
    20269 #?     (write-buffered Stderr " for type-id ")
    20270 #?     (write-int32-hex-buffered Stderr *(ebp+8))
    20271 #?     (write-buffered Stderr Newline)
    20272 #?     (flush Stderr)
    20273       # tmp->id = t
    20274       8b/-> *(ebp+8) 2/r32/edx
    20275       89/<- *eax 2/r32/edx  # Typeinfo-id
    20276       # tmp->fields = new table
    20277       # . fields = new table
    20278       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
    20279       # . tmp->fields = fields
    20280       8b/-> *ecx 2/r32/edx
    20281       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
    20282       8b/-> *(ecx+4) 2/r32/edx
    20283       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
    20284       # tmp->next = Program->types
    20285       8b/-> *_Program-types 1/r32/ecx
    20286       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
    20287       8b/-> *_Program-types->payload 1/r32/ecx
    20288       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
    20289       # Program->types = out
    20290       8b/-> *edi 1/r32/ecx
    20291       89/<- *_Program-types 1/r32/ecx
    20292       8b/-> *(edi+4) 1/r32/ecx
    20293       89/<- *_Program-types->payload 1/r32/ecx
    20294     }
    20295 $find-or-create-typeinfo:end:
    20296     # . reclaim locals
    20297     81 0/subop/add %esp 8/imm32
    20298     # . restore registers
    20299     5f/pop-to-edi
    20300     5a/pop-to-edx
    20301     59/pop-to-ecx
    20302     58/pop-to-eax
    20303     # . epilogue
    20304     89/<- %esp 5/r32/ebp
    20305     5d/pop-to-ebp
    20306     c3/return
    20307
    20308 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20309     # . prologue
    20310     55/push-ebp
    20311     89/<- %ebp 4/r32/esp
    20312     # . save registers
    20313     50/push-eax
    20314     51/push-ecx
    20315     52/push-edx
    20316     57/push-edi
    20317     # ecx = t
    20318     8b/-> *(ebp+8) 1/r32/ecx
    20319     # edi = out
    20320     8b/-> *(ebp+0xc) 7/r32/edi
    20321     # *out = Program->types
    20322     8b/-> *_Program-types 0/r32/eax
    20323     89/<- *edi 0/r32/eax
    20324     8b/-> *_Program-types->payload 0/r32/eax
    20325     89/<- *(edi+4) 0/r32/eax
    20326     {
    20327 $find-typeinfo:loop:
    20328       # if (*out == 0) break
    20329       81 7/subop/compare *edi 0/imm32
    20330       74/jump-if-= break/disp8
    20331 $find-typeinfo:check:
    20332       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20333       (lookup *edi *(edi+4))  # => eax
    20334       # if (tmp->id == t) break
    20335       39/compare *eax 1/r32/ecx  # Typeinfo-id
    20336       74/jump-if-= break/disp8
    20337 $find-typeinfo:continue:
    20338       # *out = tmp->next
    20339       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
    20340       89/<- *edi 2/r32/edx
    20341       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
    20342       89/<- *(edi+4) 2/r32/edx
    20343       #
    20344       eb/jump loop/disp8
    20345     }
    20346 $find-typeinfo:end:
    20347     # . restore registers
    20348     5f/pop-to-edi
    20349     5a/pop-to-edx
    20350     59/pop-to-ecx
    20351     58/pop-to-eax
    20352     # . epilogue
    20353     89/<- %esp 5/r32/ebp
    20354     5d/pop-to-ebp
    20355     c3/return
    20356
    20357 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
    20358     # . prologue
    20359     55/push-ebp
    20360     89/<- %ebp 4/r32/esp
    20361     # . save registers
    20362     50/push-eax
    20363     52/push-edx
    20364     57/push-edi
    20365     # var dest/edi: (handle typeinfo-entry)
    20366     68/push 0/imm32
    20367     68/push 0/imm32
    20368     89/<- %edi 4/r32/esp
    20369     # find-or-create-typeinfo-fields(T, f, dest)
    20370     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
    20371     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
    20372     (lookup *edi *(edi+4))  # => eax
    20373     89/<- %edi 0/r32/eax
    20374     # if dest-addr->output-var doesn't exist, create it
    20375     {
    20376       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
    20377       0f 85/jump-if-!= break/disp32
    20378       # dest-addr->output-var = new var(dummy name, type, -1 offset)
    20379       # . var name/eax: (handle array byte) = "field"
    20380       68/push 0/imm32
    20381       68/push 0/imm32
    20382       89/<- %eax 4/r32/esp
    20383       (slice-to-string Heap *(ebp+0xc) %eax)
    20384       # . new var
    20385       8d/copy-address *(edi+0xc) 2/r32/edx
    20386       (new-var Heap  *eax *(eax+4)  %edx)
    20387       # . reclaim name
    20388       81 0/subop/add %esp 8/imm32
    20389       # var result/edx: (addr var) = lookup(dest-addr->output-var)
    20390       (lookup *(edi+0xc) *(edi+0x10))  # => eax
    20391       89/<- %edx 0/r32/eax
    20392       # result->type = new constant type
    20393       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
    20394       (allocate Heap *Type-tree-size %eax)
    20395       (lookup *(edx+8) *(edx+0xc))  # => eax
    20396       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    20397       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
    20398       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
    20399       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
    20400       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
    20401       # result->offset isn't filled out yet
    20402       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
    20403     }
    20404     # out = dest-addr->output-var
    20405     8b/-> *(ebp+0x10) 2/r32/edx
    20406     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20407     89/<- *edx 0/r32/eax
    20408     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
    20409     89/<- *(edx+4) 0/r32/eax
    20410 $find-or-create-typeinfo-output-var:end:
    20411     # . reclaim locals
    20412     81 0/subop/add %esp 8/imm32
    20413     # . restore registers
    20414     5f/pop-to-edi
    20415     5a/pop-to-edx
    20416     58/pop-to-eax
    20417     # . epilogue
    20418     89/<- %esp 5/r32/ebp
    20419     5d/pop-to-ebp
    20420     c3/return
    20421
    20422 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
    20423     # . prologue
    20424     55/push-ebp
    20425     89/<- %ebp 4/r32/esp
    20426     # . save registers
    20427     50/push-eax
    20428     56/push-esi
    20429     57/push-edi
    20430     # eax = lookup(T->fields)
    20431     8b/-> *(ebp+8) 0/r32/eax
    20432     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
    20433     # edi = out
    20434     8b/-> *(ebp+0x10) 7/r32/edi
    20435     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
    20436     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
    20437     89/<- %esi 0/r32/eax
    20438     # if src doesn't exist, allocate it
    20439     {
    20440       81 7/subop/compare *esi 0/imm32
    20441       75/jump-if-!= break/disp8
    20442       (allocate Heap *Typeinfo-entry-size %esi)
    20443 #?       (write-buffered Stderr "handle at ")
    20444 #?       (write-int32-hex-buffered Stderr %esi)
    20445 #?       (write-buffered Stderr ": ")
    20446 #?       (write-int32-hex-buffered Stderr *esi)
    20447 #?       (write-buffered Stderr " ")
    20448 #?       (write-int32-hex-buffered Stderr *(esi+4))
    20449 #?       (write-buffered Stderr Newline)
    20450 #?       (flush Stderr)
    20451 #?       (lookup *esi *(esi+4))
    20452 #?       (write-buffered Stderr "created typeinfo fields at ")
    20453 #?       (write-int32-hex-buffered Stderr %esi)
    20454 #?       (write-buffered Stderr " for ")
    20455 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    20456 #?       (write-buffered Stderr Newline)
    20457 #?       (flush Stderr)
    20458     }
    20459     # *out = src
    20460     # . *edi = *src
    20461     8b/-> *esi 0/r32/eax
    20462     89/<- *edi 0/r32/eax
    20463     8b/-> *(esi+4) 0/r32/eax
    20464     89/<- *(edi+4) 0/r32/eax
    20465 $find-or-create-typeinfo-fields:end:
    20466     # . restore registers
    20467     5f/pop-to-edi
    20468     5e/pop-to-esi
    20469     58/pop-to-eax
    20470     # . epilogue
    20471     89/<- %esp 5/r32/ebp
    20472     5d/pop-to-ebp
    20473     c3/return
    20474
    20475 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20476     # pseudocode:
    20477     #   var line: (stream byte 512)
    20478     #   curr-index = 0
    20479     #   while true
    20480     #     clear-stream(line)
    20481     #     read-line-buffered(in, line)
    20482     #     if line->write == 0
    20483     #       abort
    20484     #     word-slice = next-mu-token(line)
    20485     #     if slice-empty?(word-slice)               # end of line
    20486     #       continue
    20487     #     if slice-equal?(word-slice, "}")
    20488     #       break
    20489     #     var v: (handle var) = parse-var-with-type(word-slice, line)
    20490     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
    20491     #     TODO: ensure that r->first is null
    20492     #     r->index = curr-index
    20493     #     curr-index++
    20494     #     r->input-var = v
    20495     #     if r->output-var == 0
    20496     #       r->output-var = new literal
    20497     #     TODO: ensure nothing else in line
    20498     # t->total-size-in-bytes = -2 (not yet initialized)
    20499     #
    20500     # . prologue
    20501     55/push-ebp
    20502     89/<- %ebp 4/r32/esp
    20503     # var curr-index: int at *(ebp-4)
    20504     68/push 0/imm32
    20505     # . save registers
    20506     50/push-eax
    20507     51/push-ecx
    20508     52/push-edx
    20509     53/push-ebx
    20510     56/push-esi
    20511     57/push-edi
    20512     # edi = t
    20513     8b/-> *(ebp+0xc) 7/r32/edi
    20514     # var line/ecx: (stream byte 512)
    20515     81 5/subop/subtract %esp 0x200/imm32
    20516     68/push 0x200/imm32/size
    20517     68/push 0/imm32/read
    20518     68/push 0/imm32/write
    20519     89/<- %ecx 4/r32/esp
    20520     # var word-slice/edx: slice
    20521     68/push 0/imm32/end
    20522     68/push 0/imm32/start
    20523     89/<- %edx 4/r32/esp
    20524     # var v/esi: (handle var)
    20525     68/push 0/imm32
    20526     68/push 0/imm32
    20527     89/<- %esi 4/r32/esp
    20528     # var r/ebx: (handle typeinfo-entry)
    20529     68/push 0/imm32
    20530     68/push 0/imm32
    20531     89/<- %ebx 4/r32/esp
    20532     {
    20533 $populate-mu-type:line-loop:
    20534       (clear-stream %ecx)
    20535       (read-line-buffered *(ebp+8) %ecx)
    20536       # if (line->write == 0) abort
    20537       81 7/subop/compare *ecx 0/imm32
    20538       0f 84/jump-if-= $populate-mu-type:error1/disp32
    20539 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
    20545       (next-mu-token %ecx %edx)
    20546       # if slice-empty?(word-slice) continue
    20547       (slice-empty? %edx)  # => eax
    20548       3d/compare-eax-and 0/imm32
    20549       0f 85/jump-if-!= loop/disp32
    20550       # if slice-equal?(word-slice, "}") break
    20551       (slice-equal? %edx "}")
    20552       3d/compare-eax-and 0/imm32
    20553       0f 85/jump-if-!= break/disp32
    20554 $populate-mu-type:parse-element:
    20555       # v = parse-var-with-type(word-slice, first-line)
    20556       # must do this first to strip the trailing ':' from word-slice before
    20557       # using it in find-or-create-typeinfo-fields below
    20558       # TODO: clean up that mutation in parse-var-with-type
    20559       (type-name *edi)  # Typeinfo-id => eax
    20560       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
    20561       # if v is an addr, abort
    20562       (lookup *esi *(esi+4))  # => eax
    20563       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20564       (mu-addr-type? %eax)  # => eax
    20565       3d/compare-eax-and 0/imm32/false
    20566       0f 85/jump-if-!= $populate-mu-type:error2/disp32
    20567       # if v is an array, abort  (we could support it, but initialization gets complex)
    20568       (lookup *esi *(esi+4))  # => eax
    20569       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20570       (mu-array-type? %eax)  # => eax
    20571       3d/compare-eax-and 0/imm32/false
    20572       0f 85/jump-if-!= $populate-mu-type:error3/disp32
    20573       # if v is a byte, abort
    20574       (lookup *esi *(esi+4))  # => eax
    20575       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20576       (simple-mu-type? %eax 8)  # byte => eax
    20577       3d/compare-eax-and 0/imm32/false
    20578       0f 85/jump-if-!= $populate-mu-type:error4/disp32
    20579       # if v is a slice, abort
    20580       (lookup *esi *(esi+4))  # => eax
    20581       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20582       (simple-mu-type? %eax 0xc)  # slice => eax
    20583       3d/compare-eax-and 0/imm32/false
    20584       0f 85/jump-if-!= $populate-mu-type:error5/disp32
    20585       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
    20586       (lookup *esi *(esi+4))  # => eax
    20587       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20588       (mu-stream-type? %eax)  # => eax
    20589       3d/compare-eax-and 0/imm32/false
    20590       0f 85/jump-if-!= $populate-mu-type:error6/disp32
    20591       # var tmp/ecx
    20592       51/push-ecx
    20593 $populate-mu-type:create-typeinfo-fields:
    20594       # var r/ebx: (handle typeinfo-entry)
    20595       (find-or-create-typeinfo-fields %edi %edx %ebx)
    20596       # r->index = curr-index
    20597       (lookup *ebx *(ebx+4))  # => eax
    20598       8b/-> *(ebp-4) 1/r32/ecx
    20599 #?       (write-buffered Stderr "saving index ")
    20600 #?       (write-int32-hex-buffered Stderr %ecx)
    20601 #?       (write-buffered Stderr " at ")
    20602 #?       (write-int32-hex-buffered Stderr %edi)
    20603 #?       (write-buffered Stderr Newline)
    20604 #?       (flush Stderr)
    20605       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
    20606       # ++curr-index
    20607       ff 0/subop/increment *(ebp-4)
    20608 $populate-mu-type:set-input-type:
    20609       # r->input-var = v
    20610       8b/-> *esi 1/r32/ecx
    20611       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
    20612       8b/-> *(esi+4) 1/r32/ecx
    20613       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
    20614       # restore line
    20615       59/pop-to-ecx
    20616       {
    20617 $populate-mu-type:create-output-type:
    20618         # if (r->output-var == 0) create a new var with some placeholder data
    20619         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
    20620         75/jump-if-!= break/disp8
    20621         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20622         (new-literal Heap %edx %eax)
    20623       }
    20624       e9/jump loop/disp32
    20625     }
    20626 $populate-mu-type:invalidate-total-size-in-bytes:
    20627     # Offsets and total size may not be accurate here since we may not yet
    20628     # have encountered the element types.
    20629     # We'll recompute them separately after parsing the entire program.
    20630     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
    20631 $populate-mu-type:end:
    20632     # . reclaim locals
    20633     81 0/subop/add %esp 0x224/imm32
    20634     # . restore registers
    20635     5f/pop-to-edi
    20636     5e/pop-to-esi
    20637     5b/pop-to-ebx
    20638     5a/pop-to-edx
    20639     59/pop-to-ecx
    20640     58/pop-to-eax
    20641     # reclaim curr-index
    20642     81 0/subop/add %esp 4/imm32
    20643     # . epilogue
    20644     89/<- %esp 5/r32/ebp
    20645     5d/pop-to-ebp
    20646     c3/return
    20647
    20648 $populate-mu-type:error1:
    20649     # error("incomplete type definition '" t->name "'\n")
    20650     (write-buffered *(ebp+0x10) "incomplete type definition '")
    20651     (type-name *edi)  # Typeinfo-id => eax
    20652     (write-buffered *(ebp+0x10) %eax)
    20653     (write-buffered *(ebp+0x10) "\n")
    20654     (flush *(ebp+0x10))
    20655     (stop *(ebp+0x14) 1)
    20656     # never gets here
    20657
    20658 $populate-mu-type:error2:
    20659     (write-buffered *(ebp+0x10) "type ")
    20660     (type-name *edi)  # Typeinfo-id => eax
    20661     (write-buffered *(ebp+0x10) %eax)
    20662     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
    20663     (flush *(ebp+0x10))
    20664     (stop *(ebp+0x14) 1)
    20665     # never gets here
    20666
    20667 $populate-mu-type:error3:
    20668     (write-buffered *(ebp+0x10) "type ")
    20669     (type-name *edi)  # Typeinfo-id => eax
    20670     (write-buffered *(ebp+0x10) %eax)
    20671     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
    20672     (flush *(ebp+0x10))
    20673     (stop *(ebp+0x14) 1)
    20674     # never gets here
    20675
    20676 $populate-mu-type:error4:
    20677     (write-buffered *(ebp+0x10) "type ")
    20678     (type-name *edi)  # Typeinfo-id => eax
    20679     (write-buffered *(ebp+0x10) %eax)
    20680     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
    20681     (flush *(ebp+0x10))
    20682     (stop *(ebp+0x14) 1)
    20683     # never gets here
    20684
    20685 $populate-mu-type:error5:
    20686     (write-buffered *(ebp+0x10) "type ")
    20687     (type-name *edi)  # Typeinfo-id => eax
    20688     (write-buffered *(ebp+0x10) %eax)
    20689     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
    20690     (flush *(ebp+0x10))
    20691     (stop *(ebp+0x14) 1)
    20692     # never gets here
    20693
    20694 $populate-mu-type:error6:
    20695     (write-buffered *(ebp+0x10) "type ")
    20696     (type-name *edi)  # Typeinfo-id => eax
    20697     (write-buffered *(ebp+0x10) %eax)
    20698     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
    20699     (flush *(ebp+0x10))
    20700     (stop *(ebp+0x14) 1)
    20701     # never gets here
    20702
    20703 type-name:  # index: int -> result/eax: (addr array byte)
    20704     # . prologue
    20705     55/push-ebp
    20706     89/<- %ebp 4/r32/esp
    20707     #
    20708     (index Type-id *(ebp+8))
    20709 $type-name:end:
    20710     # . epilogue
    20711     89/<- %esp 5/r32/ebp
    20712     5d/pop-to-ebp
    20713     c3/return
    20714
    20715 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
    20716     # . prologue
    20717     55/push-ebp
    20718     89/<- %ebp 4/r32/esp
    20719     # . save registers
    20720     56/push-esi
    20721     # TODO: bounds-check index
    20722     # esi = arr
    20723     8b/-> *(ebp+8) 6/r32/esi
    20724     # eax = index
    20725     8b/-> *(ebp+0xc) 0/r32/eax
    20726     # eax = *(arr + 12 + index)
    20727     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
    20728 $index:end:
    20729     # . restore registers
    20730     5e/pop-to-esi
    20731     # . epilogue
    20732     89/<- %esp 5/r32/ebp
    20733     5d/pop-to-ebp
    20734     c3/return
    20735
    20736 #######################################################
    20737 # Compute type sizes
    20738 #######################################################
    20739
    20740 # Compute the sizes of all user-defined types.
    20741 # We'll need the sizes of their elements, which may be other user-defined
    20742 # types, which we will compute as needed.
    20743
    20744 # Initially, all user-defined types have their sizes set to -2 (invalid)
    20745 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    20746     # . prologue
    20747     55/push-ebp
    20748     89/<- %ebp 4/r32/esp
    20749 $populate-mu-type-sizes:total-sizes:
    20750     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    20751     (lookup *_Program-types *_Program-types->payload)  # => eax
    20752     {
    20753       # if (curr == null) break
    20754       3d/compare-eax-and 0/imm32/null
    20755       74/jump-if-= break/disp8
    20756       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
    20757       # curr = lookup(curr->next)
    20758       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20759       eb/jump loop/disp8
    20760     }
    20761 $populate-mu-type-sizes:offsets:
    20762     # curr = *Program->types
    20763     (lookup *_Program-types *_Program-types->payload)  # => eax
    20764     {
    20765       # if (curr == null) break
    20766       3d/compare-eax-and 0/imm32/null
    20767       74/jump-if-= break/disp8
    20768       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
    20769       # curr = curr->next
    20770       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20771       eb/jump loop/disp8
    20772     }
    20773 $populate-mu-type-sizes:end:
    20774     # . epilogue
    20775     89/<- %esp 5/r32/ebp
    20776     5d/pop-to-ebp
    20777     c3/return
    20778
    20779 # compute sizes of all fields, recursing as necessary
    20780 # sum up all their sizes to arrive at total size
    20781 # fields may be out of order, but that doesn't affect the answer
    20782 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20783     # . prologue
    20784     55/push-ebp
    20785     89/<- %ebp 4/r32/esp
    20786     # . save registers
    20787     50/push-eax
    20788     51/push-ecx
    20789     52/push-edx
    20790     56/push-esi
    20791     57/push-edi
    20792     # esi = T
    20793     8b/-> *(ebp+8) 6/r32/esi
    20794     # if T is already computed, return
    20795     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
    20796     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
    20797     # if T is being computed, abort
    20798     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20799     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
    20800     # tag T (-2 to -1) to avoid infinite recursion
    20801     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20802     # var total-size/edi: int = 0
    20803     bf/copy-to-edi 0/imm32
    20804     # - for every field, if it's a user-defined type, compute its size
    20805     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    20806     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    20807     89/<- %ecx 0/r32/eax
    20808     # var table-size/edx: int = table->write
    20809     8b/-> *ecx 2/r32/edx  # stream-write
    20810     # var curr/ecx: (addr table_row) = table->data
    20811     8d/copy-address *(ecx+0xc) 1/r32/ecx
    20812     # var max/edx: (addr table_row) = table->data + table->write
    20813     8d/copy-address *(ecx+edx) 2/r32/edx
    20814     {
    20815 $populate-mu-type-sizes-in-type:loop:
    20816       # if (curr >= max) break
    20817       39/compare %ecx 2/r32/edx
    20818       73/jump-if-addr>= break/disp8
    20819       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
    20820       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    20821       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
    20822       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
    20823       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
    20824       # compute size of t->input-var
    20825       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    20826       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    20827       # result += eax
    20828       01/add-to %edi 0/r32/eax
    20829       # curr += row-size
    20830       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    20831       #
    20832       eb/jump loop/disp8
    20833     }
    20834     # - save result
    20835     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
    20836 $populate-mu-type-sizes-in-type:end:
    20837     # . restore registers
    20838     5f/pop-to-edi
    20839     5e/pop-to-esi
    20840     5a/pop-to-edx
    20841     59/pop-to-ecx
    20842     58/pop-to-eax
    20843     # . epilogue
    20844     89/<- %esp 5/r32/ebp
    20845     5d/pop-to-ebp
    20846     c3/return
    20847
    20848 $populate-mu-type-sizes-in-type:abort:
    20849     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
    20850     (flush *(ebp+0xc))
    20851     (stop *(ebp+0x10) 1)
    20852     # never gets here
    20853
    20854 # Analogous to size-of, except we need to compute what size-of can just read
    20855 # off the right data structures.
    20856 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20857     # . prologue
    20858     55/push-ebp
    20859     89/<- %ebp 4/r32/esp
    20860     # . push registers
    20861     51/push-ecx
    20862     # var t/ecx: (addr type-tree) = lookup(v->type)
    20863     8b/-> *(ebp+8) 1/r32/ecx
    20864     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    20865     89/<- %ecx 0/r32/eax
    20866     # if (t->is-atom == false) t = lookup(t->left)
    20867     {
    20868       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    20869       75/jump-if-!= break/disp8
    20870       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    20871       89/<- %ecx 0/r32/eax
    20872     }
    20873     # TODO: ensure t is an atom
    20874     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
    20875 $compute-size-of-var:end:
    20876     # . restore registers
    20877     59/pop-to-ecx
    20878     # . epilogue
    20879     89/<- %esp 5/r32/ebp
    20880     5d/pop-to-ebp
    20881     c3/return
    20882
    20883 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20884     # . prologue
    20885     55/push-ebp
    20886     89/<- %ebp 4/r32/esp
    20887     # . save registers
    20888     51/push-ecx
    20889     # var out/ecx: (handle typeinfo)
    20890     68/push 0/imm32
    20891     68/push 0/imm32
    20892     89/<- %ecx 4/r32/esp
    20893     # eax = t
    20894     8b/-> *(ebp+8) 0/r32/eax
    20895     # if t is a literal, return 0
    20896     3d/compare-eax-and 0/imm32/literal
    20897     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
    20898     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    20899     3d/compare-eax-and 8/imm32/byte
    20900     {
    20901       75/jump-if-!= break/disp8
    20902       b8/copy-to-eax 4/imm32
    20903       eb/jump $compute-size-of-type-id:end/disp8
    20904     }
    20905     # if t is a handle, return 8
    20906     3d/compare-eax-and 4/imm32/handle
    20907     {
    20908       75/jump-if-!= break/disp8
    20909       b8/copy-to-eax 8/imm32
    20910       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20911     }
    20912     # if t is a slice, return 8
    20913     3d/compare-eax-and 0xc/imm32/slice
    20914     {
    20915       75/jump-if-!= break/disp8
    20916       b8/copy-to-eax 8/imm32
    20917       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20918     }
    20919     # if t is a user-defined type, compute its size
    20920     # TODO: support non-atom type
    20921     (find-typeinfo %eax %ecx)
    20922     {
    20923       81 7/subop/compare *ecx 0/imm32
    20924       74/jump-if-= break/disp8
    20925 $compute-size-of-type-id:user-defined:
    20926       (lookup *ecx *(ecx+4))  # => eax
    20927       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
    20928       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    20929       eb/jump $compute-size-of-type-id:end/disp8
    20930     }
    20931     # otherwise return the word size
    20932     b8/copy-to-eax 4/imm32
    20933 $compute-size-of-type-id:end:
    20934     # . reclaim locals
    20935     81 0/subop/add %esp 8/imm32
    20936     # . restore registers
    20937     59/pop-to-ecx
    20938     # . epilogue
    20939     89/<- %esp 5/r32/ebp
    20940     5d/pop-to-ebp
    20941     c3/return
    20942
    20943 # at this point we have total sizes for all user-defined types
    20944 # compute offsets for each element
    20945 # complication: fields may be out of order
    20946 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20947     # . prologue
    20948     55/push-ebp
    20949     89/<- %ebp 4/r32/esp
    20950     # . save registers
    20951     50/push-eax
    20952     51/push-ecx
    20953     52/push-edx
    20954     53/push-ebx
    20955     56/push-esi
    20956     57/push-edi
    20957 #?     (dump-typeinfos "aaa\n")
    20958     # var curr-offset/edi: int = 0
    20959     bf/copy-to-edi 0/imm32
    20960     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
    20961     8b/-> *(ebp+8) 1/r32/ecx
    20962     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
    20963     89/<- %ecx 0/r32/eax
    20964     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
    20965     8b/-> *ecx 2/r32/edx  # stream-write
    20966     c1 5/subop/shift-right-logical  %edx 4/imm8
    20967     # var i/ebx: int = 0
    20968     bb/copy-to-ebx 0/imm32
    20969     {
    20970 $populate-mu-type-offsets:loop:
    20971       39/compare %ebx 2/r32/edx
    20972       0f 8d/jump-if->= break/disp32
    20973 #?       (write-buffered Stderr "looking up index ")
    20974 #?       (write-int32-hex-buffered Stderr %ebx)
    20975 #?       (write-buffered Stderr " in ")
    20976 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    20977 #?       (write-buffered Stderr Newline)
    20978 #?       (flush Stderr)
    20979       # var v/esi: (addr typeinfo-entry)
    20980       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
    20981       89/<- %esi 0/r32/eax
    20982       # if v is null, silently move on; we'll emit a nice error message while type-checking
    20983       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
    20984       74/jump-if-= $populate-mu-type-offsets:end/disp8
    20985       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
    20986       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
    20987       74/jump-if-= $populate-mu-type-offsets:end/disp8
    20988       # v->output-var->offset = curr-offset
    20989       # . eax: (addr var)
    20990       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
    20991       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
    20992       # curr-offset += size-of(v->input-var)
    20993       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    20994       (size-of %eax)  # => eax
    20995       01/add-to %edi 0/r32/eax
    20996       # ++i
    20997       43/increment-ebx
    20998       e9/jump loop/disp32
    20999     }
    21000 $populate-mu-type-offsets:end:
    21001     # . restore registers
    21002     5f/pop-to-edi
    21003     5e/pop-to-esi
    21004     5b/pop-to-ebx
    21005     5a/pop-to-edx
    21006     59/pop-to-ecx
    21007     58/pop-to-eax
    21008     # . epilogue
    21009     89/<- %esp 5/r32/ebp
    21010     5d/pop-to-ebp
    21011     c3/return
    21012
    21013 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)
    21014     # . prologue
    21015     55/push-ebp
    21016     89/<- %ebp 4/r32/esp
    21017     # . save registers
    21018     51/push-ecx
    21019     52/push-edx
    21020     53/push-ebx
    21021     56/push-esi
    21022     57/push-edi
    21023     # esi = table
    21024     8b/-> *(ebp+8) 6/r32/esi
    21025     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
    21026     8d/copy-address *(esi+0xc) 1/r32/ecx
    21027     # var max/edx: (addr byte) = &table->data[table->write]
    21028     8b/-> *esi 2/r32/edx
    21029     8d/copy-address *(ecx+edx) 2/r32/edx
    21030     {
    21031 $locate-typeinfo-entry-with-index:loop:
    21032       39/compare %ecx 2/r32/edx
    21033       73/jump-if-addr>= break/disp8
    21034       # var v/eax: (addr typeinfo-entry)
    21035       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    21036       # if (v->index == idx) return v
    21037       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
    21038 #?       (write-buffered Stderr "comparing ")
    21039 #?       (write-int32-hex-buffered Stderr %ebx)
    21040 #?       (write-buffered Stderr " and ")
    21041 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
    21042 #?       (write-buffered Stderr Newline)
    21043 #?       (flush Stderr)
    21044       39/compare *(ebp+0xc) 3/r32/ebx
    21045       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
    21046       # curr += Typeinfo-entry-size
    21047       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
    21048       #
    21049       eb/jump loop/disp8
    21050     }
    21051     # return 0
    21052     b8/copy-to-eax 0/imm32
    21053 $locate-typeinfo-entry-with-index:end:
    21054 #?     (write-buffered Stderr "returning ")
    21055 #?     (write-int32-hex-buffered Stderr %eax)
    21056 #?     (write-buffered Stderr Newline)
    21057 #?     (flush Stderr)
    21058     # . restore registers
    21059     5f/pop-to-edi
    21060     5e/pop-to-esi
    21061     5b/pop-to-ebx
    21062     5a/pop-to-edx
    21063     59/pop-to-ecx
    21064     # . epilogue
    21065     89/<- %esp 5/r32/ebp
    21066     5d/pop-to-ebp
    21067     c3/return
    21068
    21069 dump-typeinfos:  # hdr: (addr array byte)
    21070     # . prologue
    21071     55/push-ebp
    21072     89/<- %ebp 4/r32/esp
    21073     # . save registers
    21074     50/push-eax
    21075     #
    21076     (write-buffered Stderr *(ebp+8))
    21077     (flush Stderr)
    21078     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    21079     (lookup *_Program-types *_Program-types->payload)  # => eax
    21080     {
    21081       # if (curr == null) break
    21082       3d/compare-eax-and 0/imm32
    21083       74/jump-if-= break/disp8
    21084       (write-buffered Stderr "---\n")
    21085       (flush Stderr)
    21086       (dump-typeinfo %eax)
    21087       # curr = lookup(curr->next)
    21088       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    21089       eb/jump loop/disp8
    21090     }
    21091 $dump-typeinfos:end:
    21092     # . restore registers
    21093     58/pop-to-eax
    21094     # . epilogue
    21095     89/<- %esp 5/r32/ebp
    21096     5d/pop-to-ebp
    21097     c3/return
    21098
    21099 dump-typeinfo:  # in: (addr typeinfo)
    21100     # . prologue
    21101     55/push-ebp
    21102     89/<- %ebp 4/r32/esp
    21103     # . save registers
    21104     50/push-eax
    21105     51/push-ecx
    21106     52/push-edx
    21107     53/push-ebx
    21108     56/push-esi
    21109     57/push-edi
    21110     # esi = in
    21111     8b/-> *(ebp+8) 6/r32/esi
    21112     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    21113     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    21114     89/<- %ecx 0/r32/eax
    21115     (write-buffered Stderr "id:")
    21116     (write-int32-hex-buffered Stderr *esi)
    21117     (write-buffered Stderr "\n")
    21118     (write-buffered Stderr "fields @ ")
    21119     (write-int32-hex-buffered Stderr %ecx)
    21120     (write-buffered Stderr Newline)
    21121     (flush Stderr)
    21122     (write-buffered Stderr "  write: ")
    21123     (write-int32-hex-buffered Stderr *ecx)
    21124     (write-buffered Stderr Newline)
    21125     (flush Stderr)
    21126     (write-buffered Stderr "  read: ")
    21127     (write-int32-hex-buffered Stderr *(ecx+4))
    21128     (write-buffered Stderr Newline)
    21129     (flush Stderr)
    21130     (write-buffered Stderr "  size: ")
    21131     (write-int32-hex-buffered Stderr *(ecx+8))
    21132     (write-buffered Stderr Newline)
    21133     (flush Stderr)
    21134     # var table-size/edx: int = table->write
    21135     8b/-> *ecx 2/r32/edx  # stream-write
    21136     # var curr/ecx: (addr table_row) = table->data
    21137     8d/copy-address *(ecx+0xc) 1/r32/ecx
    21138     # var max/edx: (addr table_row) = table->data + table->write
    21139     8d/copy-address *(ecx+edx) 2/r32/edx
    21140     {
    21141 $dump-typeinfo:loop:
    21142       # if (curr >= max) break
    21143       39/compare %ecx 2/r32/edx
    21144       0f 83/jump-if-addr>= break/disp32
    21145       (write-buffered Stderr "  row:\n")
    21146       (write-buffered Stderr "    key: ")
    21147       (write-int32-hex-buffered Stderr *ecx)
    21148       (write-buffered Stderr ",")
    21149       (write-int32-hex-buffered Stderr *(ecx+4))
    21150       (write-buffered Stderr " = '")
    21151       (lookup *ecx *(ecx+4))
    21152       (write-buffered Stderr %eax)
    21153       (write-buffered Stderr "' @ ")
    21154       (write-int32-hex-buffered Stderr %eax)
    21155       (write-buffered Stderr Newline)
    21156       (flush Stderr)
    21157       (write-buffered Stderr "    value: ")
    21158       (write-int32-hex-buffered Stderr *(ecx+8))
    21159       (write-buffered Stderr ",")
    21160       (write-int32-hex-buffered Stderr *(ecx+0xc))
    21161       (write-buffered Stderr " = typeinfo-entry@")
    21162       (lookup *(ecx+8) *(ecx+0xc))
    21163       (write-int32-hex-buffered Stderr %eax)
    21164       (write-buffered Stderr Newline)
    21165       (flush Stderr)
    21166       (write-buffered Stderr "        input var@")
    21167       (dump-var 5 %eax)
    21168       (lookup *(ecx+8) *(ecx+0xc))
    21169       (write-buffered Stderr "        index: ")
    21170       (write-int32-hex-buffered Stderr *(eax+8))
    21171       (write-buffered Stderr Newline)
    21172       (flush Stderr)
    21173       (write-buffered Stderr "        output var@")
    21174       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    21175       (dump-var 5 %eax)
    21176       (flush Stderr)
    21177       # curr += row-size
    21178       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    21179       #
    21180       e9/jump loop/disp32
    21181     }
    21182 $dump-typeinfo:end:
    21183     # . restore registers
    21184     5f/pop-to-edi
    21185     5e/pop-to-esi
    21186     5b/pop-to-ebx
    21187     5a/pop-to-edx
    21188     59/pop-to-ecx
    21189     58/pop-to-eax
    21190     # . epilogue
    21191     89/<- %esp 5/r32/ebp
    21192     5d/pop-to-ebp
    21193     c3/return
    21194
    21195 dump-var:  # indent: int, v: (addr handle var)
    21196     # . prologue
    21197     55/push-ebp
    21198     89/<- %ebp 4/r32/esp
    21199     # . save registers
    21200     50/push-eax
    21201     53/push-ebx
    21202     # eax = v
    21203     8b/-> *(ebp+0xc) 0/r32/eax
    21204     #
    21205     (write-int32-hex-buffered Stderr *eax)
    21206     (write-buffered Stderr ",")
    21207     (write-int32-hex-buffered Stderr *(eax+4))
    21208     (write-buffered Stderr "->")
    21209     (lookup *eax *(eax+4))
    21210     (write-int32-hex-buffered Stderr %eax)
    21211     (write-buffered Stderr Newline)
    21212     (flush Stderr)
    21213     {
    21214       3d/compare-eax-and 0/imm32
    21215       0f 84/jump-if-= break/disp32
    21216       (emit-indent Stderr *(ebp+8))
    21217       (write-buffered Stderr "name: ")
    21218       89/<- %ebx 0/r32/eax
    21219       (write-int32-hex-buffered Stderr *ebx)  # Var-name
    21220       (write-buffered Stderr ",")
    21221       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
    21222       (write-buffered Stderr "->")
    21223       (lookup *ebx *(ebx+4))  # Var-name
    21224       (write-int32-hex-buffered Stderr %eax)
    21225       {
    21226         3d/compare-eax-and 0/imm32
    21227         74/jump-if-= break/disp8
    21228         (write-buffered Stderr Space)
    21229         (write-buffered Stderr %eax)
    21230       }
    21231       (write-buffered Stderr Newline)
    21232       (flush Stderr)
    21233       (emit-indent Stderr *(ebp+8))
    21234       (write-buffered Stderr "block depth: ")
    21235       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
    21236       (write-buffered Stderr Newline)
    21237       (flush Stderr)
    21238       (emit-indent Stderr *(ebp+8))
    21239       (write-buffered Stderr "stack offset: ")
    21240       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
    21241       (write-buffered Stderr Newline)
    21242       (flush Stderr)
    21243       (emit-indent Stderr *(ebp+8))
    21244       (write-buffered Stderr "reg: ")
    21245       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
    21246       (write-buffered Stderr ",")
    21247       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
    21248       (write-buffered Stderr "->")
    21249       (flush Stderr)
    21250       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
    21251       (write-int32-hex-buffered Stderr %eax)
    21252       {
    21253         3d/compare-eax-and 0/imm32
    21254         74/jump-if-= break/disp8
    21255         (write-buffered Stderr Space)
    21256         (write-buffered Stderr %eax)
    21257       }
    21258       (write-buffered Stderr Newline)
    21259       (flush Stderr)
    21260     }
    21261 $dump-var:end:
    21262     # . restore registers
    21263     5b/pop-to-ebx
    21264     58/pop-to-eax
    21265     # . epilogue
    21266     89/<- %esp 5/r32/ebp
    21267     5d/pop-to-ebp
    21268     c3/return
    21269
    21270 #######################################################
    21271 # Type-checking
    21272 #######################################################
    21273
    21274 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    21275     # . prologue
    21276     55/push-ebp
    21277     89/<- %ebp 4/r32/esp
    21278     # . save registers
    21279     50/push-eax
    21280     # var curr/eax: (addr function) = lookup(Program->functions)
    21281     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21282     {
    21283 $check-mu-types:loop:
    21284       # if (curr == null) break
    21285       3d/compare-eax-and 0/imm32
    21286       0f 84/jump-if-= break/disp32
    21287 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
    21295       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
    21296       # curr = lookup(curr->next)
    21297       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    21298       e9/jump loop/disp32
    21299     }
    21300 $check-mu-types:end:
    21301     # . restore registers
    21302     58/pop-to-eax
    21303     # . epilogue
    21304     89/<- %esp 5/r32/ebp
    21305     5d/pop-to-ebp
    21306     c3/return
    21307
    21308 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21309     # . prologue
    21310     55/push-ebp
    21311     89/<- %ebp 4/r32/esp
    21312     # . save registers
    21313     50/push-eax
    21314     56/push-esi
    21315     # esi = f
    21316     8b/-> *(ebp+8) 6/r32/esi
    21317     # outputs
    21318     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
    21319     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
    21320     # body
    21321     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
    21322     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    21323     # if function has no outputs, we're done
    21324     81 7/subop/compare *(esi+0x10) 0/imm32
    21325     74/jump-if-= $check-mu-function:end/disp8
    21326     # some final checks on body
    21327     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
    21328     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
    21329 $check-mu-function:end:
    21330     # . restore registers
    21331     5e/pop-to-esi
    21332     58/pop-to-eax
    21333     # . epilogue
    21334     89/<- %esp 5/r32/ebp
    21335     5d/pop-to-ebp
    21336     c3/return
    21337
    21338 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21339     # . prologue
    21340     55/push-ebp
    21341     89/<- %ebp 4/r32/esp
    21342     # . save registers
    21343     50/push-eax
    21344     # eax = block
    21345     8b/-> *(ebp+8) 0/r32/eax
    21346     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    21347     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    21348     #
    21349     {
    21350 $check-mu-block:check-empty:
    21351       3d/compare-eax-and 0/imm32
    21352       0f 84/jump-if-= break/disp32
    21353       # emit block->statements
    21354       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21355     }
    21356 $check-mu-block:end:
    21357     # . restore registers
    21358     58/pop-to-eax
    21359     # . epilogue
    21360     89/<- %esp 5/r32/ebp
    21361     5d/pop-to-ebp
    21362     c3/return
    21363
    21364 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21365     # . prologue
    21366     55/push-ebp
    21367     89/<- %ebp 4/r32/esp
    21368     # . save registers
    21369     50/push-eax
    21370     56/push-esi
    21371     # esi = stmts
    21372     8b/-> *(ebp+8) 6/r32/esi
    21373     {
    21374 $check-mu-stmt-list:loop:
    21375       81 7/subop/compare %esi 0/imm32
    21376       0f 84/jump-if-= break/disp32
    21377       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
    21378       (lookup *esi *(esi+4))  # List-value List-value => eax
    21379       {
    21380 $check-mu-stmt-list:check-for-block:
    21381         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
    21382         75/jump-if-!= break/disp8
    21383 $check-mu-stmt-list:block:
    21384         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21385         eb/jump $check-mu-stmt-list:continue/disp8
    21386       }
    21387       {
    21388 $check-mu-stmt-list:check-for-stmt1:
    21389         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    21390         0f 85/jump-if-!= break/disp32
    21391 $check-mu-stmt-list:stmt1:
    21392         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21393         eb/jump $check-mu-stmt-list:continue/disp8
    21394       }
    21395       {
    21396 $check-mu-stmt-list:check-for-reg-var-def:
    21397         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
    21398         0f 85/jump-if-!= break/disp32
    21399 $check-mu-stmt-list:reg-var-def:
    21400         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21401         eb/jump $check-mu-stmt-list:continue/disp8
    21402       }
    21403 $check-mu-stmt-list:continue:
    21404       # TODO: raise an error on unrecognized Stmt-tag
    21405       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    21406       89/<- %esi 0/r32/eax
    21407       e9/jump loop/disp32
    21408     }
    21409 $check-mu-stmt-list:end:
    21410     # . restore registers
    21411     5e/pop-to-esi
    21412     58/pop-to-eax
    21413     # . epilogue
    21414     89/<- %esp 5/r32/ebp
    21415     5d/pop-to-ebp
    21416     c3/return
    21417
    21418 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21419     # . prologue
    21420     55/push-ebp
    21421     89/<- %ebp 4/r32/esp
    21422     # . save registers
    21423     50/push-eax
    21424     # - if stmt's operation matches a primitive, check against it
    21425     (has-primitive-name? *(ebp+8))  # => eax
    21426     3d/compare-eax-and 0/imm32/false
    21427     {
    21428       74/jump-if-= break/disp8
    21429       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21430       e9/jump $check-mu-stmt:end/disp32
    21431     }
    21432     # - otherwise find a function to check against
    21433     # var f/eax: (addr function) = lookup(*Program->functions)
    21434     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21435     (find-matching-function %eax *(ebp+8))  # => eax
    21436     3d/compare-eax-and 0/imm32
    21437     {
    21438       74/jump-if-= break/disp8
    21439       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21440       eb/jump $check-mu-stmt:end/disp8
    21441     }
    21442     # var f/eax: (addr function) = lookup(*Program->signatures)
    21443     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    21444     (find-matching-function %eax *(ebp+8))  # => eax
    21445     3d/compare-eax-and 0/imm32
    21446     {
    21447       74/jump-if-= break/disp8
    21448       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21449       eb/jump $check-mu-stmt:end/disp8
    21450     }
    21451     # - otherwise abort
    21452     e9/jump $check-mu-stmt:unknown-call/disp32
    21453 $check-mu-stmt:end:
    21454     # . restore registers
    21455     58/pop-to-eax
    21456     # . epilogue
    21457     89/<- %esp 5/r32/ebp
    21458     5d/pop-to-ebp
    21459     c3/return
    21460
    21461 $check-mu-stmt:unknown-call:
    21462     (write-buffered *(ebp+0x10) "unknown function '")
    21463     8b/-> *(ebp+8) 0/r32/eax
    21464     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21465     (write-buffered *(ebp+0x10) %eax)
    21466     (write-buffered *(ebp+0x10) "'\n")
    21467     (flush *(ebp+0x10))
    21468     (stop *(ebp+0x14) 1)
    21469     # never gets here
    21470
    21471 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
    21472     # . prologue
    21473     55/push-ebp
    21474     89/<- %ebp 4/r32/esp
    21475     # . save registers
    21476     51/push-ecx
    21477     56/push-esi
    21478     # var name/esi: (addr array byte) = lookup(stmt->operation)
    21479     8b/-> *(ebp+8) 6/r32/esi
    21480     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21481     89/<- %esi 0/r32/eax
    21482     # if (name == "return") return true
    21483     (string-equal? %esi "return")  # => eax
    21484     3d/compare-eax-and 0/imm32/false
    21485     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21486     # if (name == "get") return true
    21487     (string-equal? %esi "get")  # => eax
    21488     3d/compare-eax-and 0/imm32/false
    21489     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21490     # if (name == "index") return true
    21491     (string-equal? %esi "index")  # => eax
    21492     3d/compare-eax-and 0/imm32/false
    21493     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21494     # if (name == "length") return true
    21495     (string-equal? %esi "length")  # => eax
    21496     3d/compare-eax-and 0/imm32/false
    21497     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21498     # if (name == "compute-offset") return true
    21499     (string-equal? %esi "compute-offset")  # => eax
    21500     3d/compare-eax-and 0/imm32/false
    21501     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21502     # if (name == "copy-object") return true
    21503     (string-equal? %esi "copy-object")  # => eax
    21504     3d/compare-eax-and 0/imm32/false
    21505     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21506     # if (name == "clear-object") return true
    21507     (string-equal? %esi "clear-object")  # => eax
    21508     3d/compare-eax-and 0/imm32/false
    21509     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21510     # if (name == "allocate") return true
    21511     (string-equal? %esi "allocate")  # => eax
    21512     3d/compare-eax-and 0/imm32/false
    21513     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21514     # if (name == "populate") return true
    21515     (string-equal? %esi "populate")  # => eax
    21516     3d/compare-eax-and 0/imm32/false
    21517     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21518     # if (name == "populate-stream") return true
    21519     (string-equal? %esi "populate-stream")  # => eax
    21520     3d/compare-eax-and 0/imm32/false
    21521     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21522     # if (name == "read-from-stream") return true
    21523     (string-equal? %esi "read-from-stream")  # => eax
    21524     3d/compare-eax-and 0/imm32/false
    21525     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21526     # if (name == "write-to-stream") return true
    21527     (string-equal? %esi "write-to-stream")  # => eax
    21528     3d/compare-eax-and 0/imm32/false
    21529     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21530     # var curr/ecx: (addr primitive) = Primitives
    21531     b9/copy-to-ecx Primitives/imm32
    21532     {
    21533 $has-primitive-name?:loop:
    21534       # if (curr == null) break
    21535       81 7/subop/compare %ecx 0/imm32
    21536       74/jump-if-= break/disp8
    21537       # if (primitive->name == name) return true
    21538       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
    21539 #?       (write-buffered Stderr %eax)
    21540 #?       (write-buffered Stderr Newline)
    21541 #?       (flush Stderr)
    21542       (string-equal? %esi %eax)  # => eax
    21543       3d/compare-eax-and 0/imm32/false
    21544       75/jump-if-!= $has-primitive-name?:end/disp8
    21545 $has-primitive-name?:next-primitive:
    21546       # curr = curr->next
    21547       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    21548       89/<- %ecx 0/r32/eax
    21549       #
    21550       e9/jump loop/disp32
    21551     }
    21552     # return null
    21553     b8/copy-to-eax 0/imm32
    21554 $has-primitive-name?:end:
    21555     # . restore registers
    21556     5e/pop-to-esi
    21557     59/pop-to-ecx
    21558     # . epilogue
    21559     89/<- %esp 5/r32/ebp
    21560     5d/pop-to-ebp
    21561     c3/return
    21562
    21563 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21564     # . prologue
    21565     55/push-ebp
    21566     89/<- %ebp 4/r32/esp
    21567     # . save registers
    21568     50/push-eax
    21569     51/push-ecx
    21570     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    21571     8b/-> *(ebp+8) 0/r32/eax
    21572     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21573     89/<- %ecx 0/r32/eax
    21574     # if (op == "copy") check-mu-copy-stmt
    21575     {
    21576       (string-equal? %ecx "copy")  # => eax
    21577       3d/compare-eax-and 0/imm32/false
    21578       74/jump-if-= break/disp8
    21579       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21580       e9/jump $check-mu-primitive:end/disp32
    21581     }
    21582     # if (op == "copy-to") check-mu-copy-to-stmt
    21583     {
    21584       (string-equal? %ecx "copy-to")  # => eax
    21585       3d/compare-eax-and 0/imm32/false
    21586       74/jump-if-= break/disp8
    21587       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21588       e9/jump $check-mu-primitive:end/disp32
    21589     }
    21590     # if (op == "copy-byte") check-mu-copy-byte-stmt
    21591     {
    21592       (string-equal? %ecx "copy-byte")  # => eax
    21593       3d/compare-eax-and 0/imm32/false
    21594       74/jump-if-= break/disp8
    21595       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21596       e9/jump $check-mu-primitive:end/disp32
    21597     }
    21598     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
    21599     {
    21600       (string-equal? %ecx "copy-byte-to")  # => eax
    21601       3d/compare-eax-and 0/imm32/false
    21602       74/jump-if-= break/disp8
    21603       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21604       e9/jump $check-mu-primitive:end/disp32
    21605     }
    21606     # if (op == "compare") check-mu-compare-stmt
    21607     {
    21608       (string-equal? %ecx "compare")  # => eax
    21609       3d/compare-eax-and 0/imm32/false
    21610       74/jump-if-= break/disp8
    21611       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21612       e9/jump $check-mu-primitive:end/disp32
    21613     }
    21614     # if (op == "address") check-mu-address-stmt
    21615     {
    21616       (string-equal? %ecx "address")  # => eax
    21617       3d/compare-eax-and 0/imm32/false
    21618       74/jump-if-= break/disp8
    21619       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21620       e9/jump $check-mu-primitive:end/disp32
    21621     }
    21622     # if (op == "return") check-mu-return-stmt
    21623     {
    21624       (string-equal? %ecx "return")  # => eax
    21625       3d/compare-eax-and 0/imm32/false
    21626       74/jump-if-= break/disp8
    21627       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21628       e9/jump $check-mu-primitive:end/disp32
    21629     }
    21630     # if (op == "get") check-mu-get-stmt
    21631     {
    21632       (string-equal? %ecx "get")  # => eax
    21633       3d/compare-eax-and 0/imm32/false
    21634       74/jump-if-= break/disp8
    21635       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21636       e9/jump $check-mu-primitive:end/disp32
    21637     }
    21638     # if (op == "index") check-mu-index-stmt
    21639     {
    21640       (string-equal? %ecx "index")  # => eax
    21641       3d/compare-eax-and 0/imm32/false
    21642       74/jump-if-= break/disp8
    21643       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21644       e9/jump $check-mu-primitive:end/disp32
    21645     }
    21646     # if (op == "length") check-mu-length-stmt
    21647     {
    21648       (string-equal? %ecx "length")  # => eax
    21649       3d/compare-eax-and 0/imm32/false
    21650       74/jump-if-= break/disp8
    21651       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21652       e9/jump $check-mu-primitive:end/disp32
    21653     }
    21654     # if (op == "compute-offset") check-mu-compute-offset-stmt
    21655     {
    21656       (string-equal? %ecx "compute-offset")  # => eax
    21657       3d/compare-eax-and 0/imm32/false
    21658       74/jump-if-= break/disp8
    21659       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21660       e9/jump $check-mu-primitive:end/disp32
    21661     }
    21662     # if (op == "copy-object") check-mu-copy-object-stmt
    21663     {
    21664       (string-equal? %ecx "copy-object")  # => eax
    21665       3d/compare-eax-and 0/imm32/false
    21666       74/jump-if-= break/disp8
    21667       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21668       e9/jump $check-mu-primitive:end/disp32
    21669     }
    21670     # if (op == "clear-object") check-mu-clear-object-stmt
    21671     {
    21672       (string-equal? %ecx "clear-object")  # => eax
    21673       3d/compare-eax-and 0/imm32/false
    21674       74/jump-if-= break/disp8
    21675       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21676       e9/jump $check-mu-primitive:end/disp32
    21677     }
    21678     # if (op == "allocate") check-mu-allocate-stmt
    21679     {
    21680       (string-equal? %ecx "allocate")  # => eax
    21681       3d/compare-eax-and 0/imm32/false
    21682       74/jump-if-= break/disp8
    21683       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21684       e9/jump $check-mu-primitive:end/disp32
    21685     }
    21686     # if (op == "populate") check-mu-populate-stmt
    21687     {
    21688       (string-equal? %ecx "populate")  # => eax
    21689       3d/compare-eax-and 0/imm32/false
    21690       74/jump-if-= break/disp8
    21691       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21692       e9/jump $check-mu-primitive:end/disp32
    21693     }
    21694     # if (op == "populate-stream") check-mu-populate-stream-stmt
    21695     {
    21696       (string-equal? %ecx "populate-stream")  # => eax
    21697       3d/compare-eax-and 0/imm32/false
    21698       74/jump-if-= break/disp8
    21699       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21700       e9/jump $check-mu-primitive:end/disp32
    21701     }
    21702     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
    21703     {
    21704       (string-equal? %ecx "read-from-stream")  # => eax
    21705       3d/compare-eax-and 0/imm32/false
    21706       74/jump-if-= break/disp8
    21707       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21708       e9/jump $check-mu-primitive:end/disp32
    21709     }
    21710     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
    21711     {
    21712       (string-equal? %ecx "write-to-stream")  # => eax
    21713       3d/compare-eax-and 0/imm32/false
    21714       74/jump-if-= break/disp8
    21715       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21716       e9/jump $check-mu-primitive:end/disp32
    21717     }
    21718     # if (op == "convert") check-mu-convert-stmt
    21719     {
    21720       (string-equal? %ecx "convert")  # => eax
    21721       3d/compare-eax-and 0/imm32/false
    21722       74/jump-if-= break/disp8
    21723       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21724       e9/jump $check-mu-primitive:end/disp32
    21725     }
    21726     # otherwise check-numberlike-stmt
    21727     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21728 $check-mu-primitive:end:
    21729     # . restore registers
    21730     59/pop-to-ecx
    21731     58/pop-to-eax
    21732     # . epilogue
    21733     89/<- %esp 5/r32/ebp
    21734     5d/pop-to-ebp
    21735     c3/return
    21736
    21737 # by default, Mu primitives should only operate on 'number-like' types
    21738 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21739     # . prologue
    21740     55/push-ebp
    21741     89/<- %ebp 4/r32/esp
    21742     # . save registers
    21743     50/push-eax
    21744     51/push-ecx
    21745     56/push-esi
    21746     # esi = stmt
    21747     8b/-> *(ebp+8) 6/r32/esi
    21748     # var gas/ecx: int = 2
    21749     b9/copy-to-ecx 2/imm32
    21750     # - check at most 1 output
    21751     # var output/eax: (addr stmt-var) = stmt->outputs
    21752     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    21753     {
    21754       3d/compare-eax-and 0/imm32
    21755       74/jump-if-= break/disp8
    21756 $check-mu-numberlike-primitive:output:
    21757       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21758       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21759       3d/compare-eax-and 0/imm32
    21760       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
    21761       # check output is in a register
    21762       # --gas
    21763       49/decrement-ecx
    21764     }
    21765     # - check first inout
    21766     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    21767     {
    21768       3d/compare-eax-and 0/imm32
    21769       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
    21770 $check-mu-numberlike-primitive:first-inout:
    21771       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21772       # --gas
    21773       49/decrement-ecx
    21774     }
    21775     # - check second inout
    21776     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21777     {
    21778       3d/compare-eax-and 0/imm32
    21779       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
    21780 $check-mu-numberlike-primitive:second-inout:
    21781       # is a second inout allowed?
    21782       81 7/subop/compare %ecx 0/imm32
    21783       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21784 $check-mu-numberlike-primitive:second-inout-permitted:
    21785       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21786     }
    21787 $check-mu-numberlike-primitive:third-inout:
    21788     # if there's a third arg, raise an error
    21789     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    21790     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21791 $check-mu-numberlike-primitive:end:
    21792     # . restore registers
    21793     5e/pop-to-esi
    21794     59/pop-to-ecx
    21795     58/pop-to-eax
    21796     # . epilogue
    21797     89/<- %esp 5/r32/ebp
    21798     5d/pop-to-ebp
    21799     c3/return
    21800
    21801 $check-mu-numberlike-primitive:error-too-many-inouts:
    21802     (write-buffered *(ebp+0x10) "fn ")
    21803     8b/-> *(ebp+0xc) 0/r32/eax
    21804     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21805     (write-buffered *(ebp+0x10) %eax)
    21806     (write-buffered *(ebp+0x10) ": stmt ")
    21807     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21808     (write-buffered *(ebp+0x10) %eax)
    21809     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
    21810     (flush *(ebp+0x10))
    21811     (stop *(ebp+0x14) 1)
    21812     # never gets here
    21813
    21814 $check-mu-numberlike-primitive:error-too-many-outputs:
    21815     (write-buffered *(ebp+0x10) "fn ")
    21816     8b/-> *(ebp+0xc) 0/r32/eax
    21817     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21818     (write-buffered *(ebp+0x10) %eax)
    21819     (write-buffered *(ebp+0x10) ": stmt ")
    21820     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21821     (write-buffered *(ebp+0x10) %eax)
    21822     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
    21823     (flush *(ebp+0x10))
    21824     (stop *(ebp+0x14) 1)
    21825     # never gets here
    21826
    21827 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21828     # . prologue
    21829     55/push-ebp
    21830     89/<- %ebp 4/r32/esp
    21831     # . save registers
    21832     50/push-eax
    21833     56/push-esi
    21834     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21835     8b/-> *(ebp+8) 0/r32/eax
    21836     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21837     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21838     89/<- %esi 0/r32/eax
    21839 $check-mu-numberlike-arg:check-literal:
    21840     # if t is an int, return
    21841     (simple-mu-type? %esi 0)  # literal => eax
    21842     3d/compare-eax-and 0/imm32/false
    21843     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
    21844 $check-mu-numberlike-arg:check-addr:
    21845     # if t is an addr and v is dereferenced, return whether t->payload is an addr
    21846     {
    21847       (mu-addr-type? %esi)  # => eax
    21848       3d/compare-eax-and 0/imm32/false
    21849       74/jump-if-= break/disp8
    21850       8b/-> *(ebp+8) 0/r32/eax
    21851       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
    21852       3d/compare-eax-and 0/imm32/false
    21853       {
    21854         74/jump-if-= break/disp8
    21855         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    21856         # if t->right is null, t = t->left
    21857         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    21858         {
    21859           75/jump-if-!= break/disp8
    21860           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    21861         }
    21862         (mu-addr-type? %eax)  # => eax
    21863         3d/compare-eax-and 0/imm32/false
    21864         74/jump-if-= $check-mu-numberlike-arg:end/disp8
    21865       }
    21866     }
    21867 $check-mu-numberlike-arg:output-checks:
    21868     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    21869 $check-mu-numberlike-arg:end:
    21870     # . restore registers
    21871     5e/pop-to-esi
    21872     58/pop-to-eax
    21873     # . epilogue
    21874     89/<- %esp 5/r32/ebp
    21875     5d/pop-to-ebp
    21876     c3/return
    21877
    21878 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21879     # . prologue
    21880     55/push-ebp
    21881     89/<- %ebp 4/r32/esp
    21882     # . save registers
    21883     50/push-eax
    21884     #
    21885     (mu-numberlike-output-var? *(ebp+8))  # => eax
    21886     3d/compare-eax-and 0/imm32/false
    21887     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
    21888 $check-mu-numberlike-output:end:
    21889     # . restore registers
    21890     58/pop-to-eax
    21891     # . epilogue
    21892     89/<- %esp 5/r32/ebp
    21893     5d/pop-to-ebp
    21894     c3/return
    21895
    21896 $check-mu-numberlike-output:fail:
    21897     # otherwise raise an error
    21898     (write-buffered *(ebp+0x14) "fn ")
    21899     8b/-> *(ebp+0x10) 0/r32/eax
    21900     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21901     (write-buffered *(ebp+0x14) %eax)
    21902     (write-buffered *(ebp+0x14) ": stmt ")
    21903     8b/-> *(ebp+0xc) 0/r32/eax
    21904     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21905     (write-buffered *(ebp+0x14) %eax)
    21906     (write-buffered *(ebp+0x14) ": '")
    21907     8b/-> *(ebp+8) 0/r32/eax
    21908     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21909     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    21910     (write-buffered *(ebp+0x14) %eax)
    21911     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
    21912     (flush *(ebp+0x14))
    21913     (stop *(ebp+0x18) 1)
    21914     # never gets here
    21915
    21916 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
    21917     # . prologue
    21918     55/push-ebp
    21919     89/<- %ebp 4/r32/esp
    21920     #
    21921     8b/-> *(ebp+8) 0/r32/eax
    21922     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21923     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21924     (mu-numberlike-output? %eax)  # => eax
    21925 $mu-numberlike-output-var?:end:
    21926     # . epilogue
    21927     89/<- %esp 5/r32/ebp
    21928     5d/pop-to-ebp
    21929     c3/return
    21930
    21931 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
    21932     # . prologue
    21933     55/push-ebp
    21934     89/<- %ebp 4/r32/esp
    21935     # . save registers
    21936     56/push-esi
    21937     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21938     8b/-> *(ebp+8) 6/r32/esi
    21939 $mu-numberlike-output?:check-int:
    21940     # if t is an int, return
    21941     (simple-mu-type? %esi 1)  # int => eax
    21942     3d/compare-eax-and 0/imm32/false
    21943     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
    21944 $mu-numberlike-output?:check-float:
    21945     # if t is a float, return
    21946     (simple-mu-type? %esi 0xf)  # float => eax
    21947     3d/compare-eax-and 0/imm32/false
    21948     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21949 $mu-numberlike-output?:check-boolean:
    21950     # if t is a boolean, return
    21951     (simple-mu-type? %esi 5)  # boolean => eax
    21952     3d/compare-eax-and 0/imm32/false
    21953     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21954 $mu-numberlike-output?:check-byte:
    21955     # if t is a byte, return
    21956     (simple-mu-type? %esi 8)  # byte => eax
    21957     3d/compare-eax-and 0/imm32/false
    21958     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21959 $mu-numberlike-output?:check-code-point:
    21960     # if t is a code-point, return
    21961     (simple-mu-type? %esi 0xd)  # code-point => eax
    21962     3d/compare-eax-and 0/imm32/false
    21963     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21964 $mu-numberlike-output?:check-grapheme:
    21965     # if t is a grapheme, return
    21966     (simple-mu-type? %esi 0xe)  # grapheme => eax
    21967     3d/compare-eax-and 0/imm32/false
    21968     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21969 $mu-numberlike-output?:return-false:
    21970     b8/copy-to-eax 0/imm32/false
    21971     eb/jump $mu-numberlike-output?:end/disp8
    21972 $mu-numberlike-output?:return-true:
    21973     b8/copy-to-eax 1/imm32/true
    21974 $mu-numberlike-output?:end:
    21975     # . restore registers
    21976     5e/pop-to-esi
    21977     # . epilogue
    21978     89/<- %esp 5/r32/ebp
    21979     5d/pop-to-ebp
    21980     c3/return
    21981
    21982 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21983     # . prologue
    21984     55/push-ebp
    21985     89/<- %ebp 4/r32/esp
    21986     # . save registers
    21987     50/push-eax
    21988     51/push-ecx
    21989     52/push-edx
    21990     56/push-esi
    21991     57/push-edi
    21992     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    21993     81 5/subop/subtract %esp 0x60/imm32
    21994     68/push 0x60/imm32/size
    21995     68/push 0/imm32/read
    21996     68/push 0/imm32/write
    21997     89/<- %edx 4/r32/esp
    21998 $check-mu-copy-stmt:get-output:
    21999     # esi = stmt
    22000     8b/-> *(ebp+8) 6/r32/esi
    22001     # var output/edi: (addr stmt-var) = stmt->outputs
    22002     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22003     89/<- %edi 0/r32/eax
    22004     # zero outputs
    22005     3d/compare-eax-and 0/imm32
    22006     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
    22007     # > 1 output
    22008     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22009     3d/compare-eax-and 0/imm32
    22010     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
    22011 $check-mu-copy-stmt:get-inout:
    22012     # var inout/esi: (addr stmt-var) = stmt->inouts
    22013     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22014     89/<- %esi 0/r32/eax
    22015     # zero inouts
    22016     3d/compare-eax-and 0/imm32
    22017     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
    22018     # > 1 inout
    22019     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22020     3d/compare-eax-and 0/imm32
    22021     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
    22022 $check-mu-copy-stmt:types:
    22023     # if inout is not a scalar, abort
    22024     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22025     (size-of %eax)  # => eax
    22026     3d/compare-eax-and 4/imm32
    22027     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
    22028     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22029     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22030     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22031     89/<- %ecx 0/r32/eax
    22032     # if (inout->is-deref?) inout-type = inout-type->payload
    22033     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22034     3d/compare-eax-and 0/imm32/false
    22035     {
    22036       74/jump-if-= break/disp8
    22037       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22038       # if inout-type->right is null, t = inout-type->left
    22039       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22040       {
    22041         75/jump-if-!= break/disp8
    22042         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22043       }
    22044       89/<- %ecx 0/r32/eax
    22045     }
    22046     # if output not in register, abort
    22047     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22048     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22049     3d/compare-eax-and 0/imm32
    22050     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
    22051     # var output-type/eax: (addr type-tree) = output->value->type
    22052     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22053     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22054     # if (inout-type == output-type) return
    22055     (type-match? %eax %ecx %edx)  # => eax
    22056     3d/compare-eax-and 0/imm32
    22057     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
    22058     # if output is an addr and inout is 0, return
    22059     {
    22060       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22061       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22062       (mu-addr-type? %eax)  # => eax
    22063       3d/compare-eax-and 0/imm32/false
    22064       74/jump-if-= break/disp8
    22065       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22066       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22067       (string-equal? %eax "0")  # => eax
    22068       3d/compare-eax-and 0/imm32/false
    22069       74/jump-if-= break/disp8
    22070       e9/jump $check-mu-copy-stmt:end/disp32
    22071     }
    22072     # if output is an offset and inout is 0, return
    22073     {
    22074       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22075       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22076       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    22077       75/jump-if-!= break/disp8
    22078       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22079       (simple-mu-type? %eax 7)  # offset => eax
    22080       3d/compare-eax-and 0/imm32/false
    22081       74/jump-if-= break/disp8
    22082       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22083       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22084       (string-equal? %eax "0")  # => eax
    22085       3d/compare-eax-and 0/imm32/false
    22086       74/jump-if-= break/disp8
    22087       e9/jump $check-mu-copy-stmt:end/disp32
    22088     }
    22089     # if output is a byte, abort if inout is not a literal. Otherwise return.
    22090     {
    22091       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22092       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22093       (simple-mu-type? %eax 8)  # byte => eax
    22094       3d/compare-eax-and 0/imm32/false
    22095       74/jump-if-= break/disp8
    22096       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22097       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22098       (simple-mu-type? %eax 0)  # literal => eax
    22099       3d/compare-eax-and 0/imm32/false
    22100       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
    22101       eb/jump $check-mu-copy-stmt:end/disp8
    22102     }
    22103     # if output is not number-like, abort
    22104     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22105 $check-mu-copy-stmt:end:
    22106     # . reclaim locals
    22107     81 0/subop/add %esp 0x6c/imm32
    22108     # . restore registers
    22109     5f/pop-to-edi
    22110     5e/pop-to-esi
    22111     5a/pop-to-edx
    22112     59/pop-to-ecx
    22113     58/pop-to-eax
    22114     # . epilogue
    22115     89/<- %esp 5/r32/ebp
    22116     5d/pop-to-ebp
    22117     c3/return
    22118
    22119 $check-mu-copy-stmt:error-no-inout:
    22120     (write-buffered *(ebp+0x10) "fn ")
    22121     8b/-> *(ebp+0xc) 0/r32/eax
    22122     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22123     (write-buffered *(ebp+0x10) %eax)
    22124     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
    22125     (flush *(ebp+0x10))
    22126     (stop *(ebp+0x14) 1)
    22127     # never gets here
    22128
    22129 $check-mu-copy-stmt:error-too-many-inouts:
    22130     (write-buffered *(ebp+0x10) "fn ")
    22131     8b/-> *(ebp+0xc) 0/r32/eax
    22132     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22133     (write-buffered *(ebp+0x10) %eax)
    22134     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
    22135     (flush *(ebp+0x10))
    22136     (stop *(ebp+0x14) 1)
    22137     # never gets here
    22138
    22139 $check-mu-copy-stmt:error-no-output:
    22140     (write-buffered *(ebp+0x10) "fn ")
    22141     8b/-> *(ebp+0xc) 0/r32/eax
    22142     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22143     (write-buffered *(ebp+0x10) %eax)
    22144     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
    22145     (flush *(ebp+0x10))
    22146     (stop *(ebp+0x14) 1)
    22147     # never gets here
    22148
    22149 $check-mu-copy-stmt:error-output-not-in-register:
    22150     (write-buffered *(ebp+0x10) "fn ")
    22151     8b/-> *(ebp+0xc) 0/r32/eax
    22152     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22153     (write-buffered *(ebp+0x10) %eax)
    22154     (write-buffered *(ebp+0x10) ": stmt copy: output '")
    22155     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22156     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22157     (write-buffered *(ebp+0x10) %eax)
    22158     (write-buffered *(ebp+0x10) "' not in a register\n")
    22159     (flush *(ebp+0x10))
    22160     (stop *(ebp+0x14) 1)
    22161     # never gets here
    22162
    22163 $check-mu-copy-stmt:error-too-many-outputs:
    22164     (write-buffered *(ebp+0x10) "fn ")
    22165     8b/-> *(ebp+0xc) 0/r32/eax
    22166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22167     (write-buffered *(ebp+0x10) %eax)
    22168     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
    22169     (flush *(ebp+0x10))
    22170     (stop *(ebp+0x14) 1)
    22171     # never gets here
    22172
    22173 $check-mu-copy-stmt:error-inout-too-large:
    22174     (write-buffered *(ebp+0x10) "fn ")
    22175     8b/-> *(ebp+0xc) 0/r32/eax
    22176     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22177     (write-buffered *(ebp+0x10) %eax)
    22178     (write-buffered *(ebp+0x10) ": stmt copy: '")
    22179     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22180     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22181     (write-buffered *(ebp+0x10) %eax)
    22182     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22183     (flush *(ebp+0x10))
    22184     (stop *(ebp+0x14) 1)
    22185     # never gets here
    22186
    22187 $check-mu-copy-stmt:error-non-literal-to-byte:
    22188     (write-buffered *(ebp+0x10) "fn ")
    22189     8b/-> *(ebp+0xc) 0/r32/eax
    22190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22191     (write-buffered *(ebp+0x10) %eax)
    22192     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
    22193     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22194     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22195     (write-buffered *(ebp+0x10) %eax)
    22196     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
    22197     (flush *(ebp+0x10))
    22198     (stop *(ebp+0x14) 1)
    22199     # never gets here
    22200
    22201 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22202     # . prologue
    22203     55/push-ebp
    22204     89/<- %ebp 4/r32/esp
    22205     # . save registers
    22206     50/push-eax
    22207     51/push-ecx
    22208     52/push-edx
    22209     53/push-ebx
    22210     56/push-esi
    22211     57/push-edi
    22212     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22213     81 5/subop/subtract %esp 0x60/imm32
    22214     68/push 0x60/imm32/size
    22215     68/push 0/imm32/read
    22216     68/push 0/imm32/write
    22217     89/<- %edx 4/r32/esp
    22218     # esi = stmt
    22219     8b/-> *(ebp+8) 6/r32/esi
    22220 $check-mu-copy-to-stmt:check-for-output:
    22221     # if stmt->outputs abort
    22222     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22223     3d/compare-eax-and 0/imm32
    22224     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
    22225 $check-mu-copy-to-stmt:get-dest:
    22226     # var dest/edi: (addr stmt-var) = stmt->inouts
    22227     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22228     89/<- %edi 0/r32/eax
    22229     # zero inouts
    22230     3d/compare-eax-and 0/imm32
    22231     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22232 $check-mu-copy-to-stmt:get-src:
    22233     # var src/esi: (addr stmt-var) = dest->next
    22234     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22235     89/<- %esi 0/r32/eax
    22236     # 1 inout
    22237     3d/compare-eax-and 0/imm32
    22238     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22239     # > 2 inouts
    22240     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22241     3d/compare-eax-and 0/imm32
    22242     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22243 $check-mu-copy-to-stmt:types:
    22244     # if src is not a scalar, abort
    22245     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22246     (size-of %eax)  # => eax
    22247     3d/compare-eax-and 4/imm32
    22248     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
    22249     # var src-type/ecx: (addr type-tree) = src->value->type
    22250     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22251     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22252     89/<- %ecx 0/r32/eax
    22253     # if src not in register or literal, abort
    22254     # (we can't use stack-offset because it hasn't been computed yet)
    22255     {
    22256       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22257       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22258       (simple-mu-type? %eax 0)  # => eax
    22259       3d/compare-eax-and 0/imm32
    22260       75/jump-if-!= break/disp8
    22261       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22262       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22263       3d/compare-eax-and 0/imm32
    22264       75/jump-if-!= break/disp8
    22265       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
    22266     }
    22267     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22268     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22269     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22270     89/<- %ebx 0/r32/eax
    22271     # if (dest->is-deref?) dest-type = dest-type->payload
    22272 $check-mu-copy-to-stmt:check-dest-deref:
    22273     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22274     3d/compare-eax-and 0/imm32/false
    22275     {
    22276       74/jump-if-= break/disp8
    22277       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22278 $check-mu-copy-to-stmt:dest-is-deref:
    22279       # if dest-type->right is null, dest-type = dest-type->left
    22280       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22281       {
    22282         75/jump-if-!= break/disp8
    22283 $check-mu-copy-to-stmt:dest-is-deref2:
    22284         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22285       }
    22286       89/<- %ebx 0/r32/eax
    22287     }
    22288     # if dest is a byte and src is not a literal, abort
    22289     {
    22290 $check-mu-copy-to-stmt:final-check-byte:
    22291       (simple-mu-type? %ebx 8)  # byte => eax
    22292       3d/compare-eax-and 0/imm32/false
    22293       74/jump-if-= break/disp8
    22294       (simple-mu-type? %ecx 0)  # literal => eax
    22295       3d/compare-eax-and 0/imm32/false
    22296       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
    22297     }
    22298     # if (src-type == dest-type) return
    22299     (type-match? %ebx %ecx %edx)  # => eax
    22300     3d/compare-eax-and 0/imm32
    22301     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
    22302     # if dest is an addr and src is 0, return
    22303     {
    22304 $check-mu-copy-to-stmt:final-check-addr:
    22305       (mu-addr-type? %ebx)  # => eax
    22306       3d/compare-eax-and 0/imm32/false
    22307       74/jump-if-= break/disp8
    22308       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22309       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22310       (string-equal? %eax "0")  # => eax
    22311       3d/compare-eax-and 0/imm32/false
    22312       74/jump-if-= break/disp8
    22313       e9/jump $check-mu-copy-to-stmt:end/disp32
    22314     }
    22315     # if dest is an offset and src is 0, return
    22316     {
    22317 $check-mu-copy-to-stmt:final-check-offset:
    22318       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    22319       75/jump-if-!= break/disp8
    22320       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    22321       (simple-mu-type? %eax 7)  # offset => eax
    22322       3d/compare-eax-and 0/imm32/false
    22323       74/jump-if-= break/disp8
    22324       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22325       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22326       (string-equal? %eax "0")  # => eax
    22327       3d/compare-eax-and 0/imm32/false
    22328       74/jump-if-= break/disp8
    22329       e9/jump $check-mu-copy-to-stmt:end/disp32
    22330     }
    22331     # if dest is not number-like, abort
    22332     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22333 $check-mu-copy-to-stmt:end:
    22334     # . reclaim locals
    22335     81 0/subop/add %esp 0x6c/imm32
    22336     # . restore registers
    22337     5f/pop-to-edi
    22338     5e/pop-to-esi
    22339     5b/pop-to-ebx
    22340     5a/pop-to-edx
    22341     59/pop-to-ecx
    22342     58/pop-to-eax
    22343     # . epilogue
    22344     89/<- %esp 5/r32/ebp
    22345     5d/pop-to-ebp
    22346     c3/return
    22347
    22348 $check-mu-copy-to-stmt:error-incorrect-inouts:
    22349     (write-buffered *(ebp+0x10) "fn ")
    22350     8b/-> *(ebp+0xc) 0/r32/eax
    22351     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22352     (write-buffered *(ebp+0x10) %eax)
    22353     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
    22354     (flush *(ebp+0x10))
    22355     (stop *(ebp+0x14) 1)
    22356     # never gets here
    22357
    22358 $check-mu-copy-to-stmt:error-too-many-outputs:
    22359     (write-buffered *(ebp+0x10) "fn ")
    22360     8b/-> *(ebp+0xc) 0/r32/eax
    22361     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22362     (write-buffered *(ebp+0x10) %eax)
    22363     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
    22364     (flush *(ebp+0x10))
    22365     (stop *(ebp+0x14) 1)
    22366     # never gets here
    22367
    22368 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
    22369     (write-buffered *(ebp+0x10) "fn ")
    22370     8b/-> *(ebp+0xc) 0/r32/eax
    22371     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22372     (write-buffered *(ebp+0x10) %eax)
    22373     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
    22374     (flush *(ebp+0x10))
    22375     (stop *(ebp+0x14) 1)
    22376     # never gets here
    22377
    22378 $check-mu-copy-to-stmt:error-src-too-large:
    22379     (write-buffered *(ebp+0x10) "fn ")
    22380     8b/-> *(ebp+0xc) 0/r32/eax
    22381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22382     (write-buffered *(ebp+0x10) %eax)
    22383     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
    22384     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22385     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22386     (write-buffered *(ebp+0x10) %eax)
    22387     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22388     (flush *(ebp+0x10))
    22389     (stop *(ebp+0x14) 1)
    22390     # never gets here
    22391
    22392 $check-mu-copy-to-stmt:error-non-literal-to-byte:
    22393     (write-buffered *(ebp+0x10) "fn ")
    22394     8b/-> *(ebp+0xc) 0/r32/eax
    22395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22396     (write-buffered *(ebp+0x10) %eax)
    22397     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
    22398     (flush *(ebp+0x10))
    22399     (stop *(ebp+0x14) 1)
    22400     # never gets here
    22401
    22402 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22403     # . prologue
    22404     55/push-ebp
    22405     89/<- %ebp 4/r32/esp
    22406     # . save registers
    22407     50/push-eax
    22408     51/push-ecx
    22409     52/push-edx
    22410     56/push-esi
    22411     57/push-edi
    22412     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22413     81 5/subop/subtract %esp 0x60/imm32
    22414     68/push 0x60/imm32/size
    22415     68/push 0/imm32/read
    22416     68/push 0/imm32/write
    22417     89/<- %edx 4/r32/esp
    22418 $check-mu-copy-byte-stmt:get-output:
    22419     # esi = stmt
    22420     8b/-> *(ebp+8) 6/r32/esi
    22421     # var output/edi: (addr stmt-var) = stmt->outputs
    22422     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22423     89/<- %edi 0/r32/eax
    22424     # zero outputs
    22425     3d/compare-eax-and 0/imm32
    22426     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
    22427     # > 1 output
    22428     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22429     3d/compare-eax-and 0/imm32
    22430     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
    22431 $check-mu-copy-byte-stmt:get-inout:
    22432     # var inout/esi: (addr stmt-var) = stmt->inouts
    22433     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22434     89/<- %esi 0/r32/eax
    22435     # zero inouts
    22436     3d/compare-eax-and 0/imm32
    22437     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
    22438     # > 1 inout
    22439     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22440     3d/compare-eax-and 0/imm32
    22441     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
    22442 $check-mu-copy-byte-stmt:types:
    22443     # if inout is not a scalar, abort
    22444     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22445     (size-of %eax)  # => eax
    22446     3d/compare-eax-and 4/imm32
    22447     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
    22448     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22449     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22450     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22451     89/<- %ecx 0/r32/eax
    22452 $check-mu-copy-byte-stmt:check-inout-deref:
    22453     # if (inout->is-deref?) inout-type = inout-type->payload
    22454     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22455     3d/compare-eax-and 0/imm32/false
    22456     {
    22457       74/jump-if-= break/disp8
    22458 $check-mu-copy-byte-stmt:inout-is-deref:
    22459       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22460       # if inout-type->right is null, t = inout-type->left
    22461       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22462       {
    22463         75/jump-if-!= break/disp8
    22464 $check-mu-copy-byte-stmt:inout-is-deref2:
    22465         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22466       }
    22467       89/<- %ecx 0/r32/eax
    22468     }
    22469     # if output not in register, abort
    22470     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22471     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22472     3d/compare-eax-and 0/imm32
    22473     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
    22474     # var output-type/eax: (addr type-tree) = output->value->type
    22475     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22476     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22477     # if output is not of type byte, abort
    22478     (simple-mu-type? %eax 8)  # byte => eax
    22479     3d/compare-eax-and 0/imm32
    22480     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
    22481 $check-mu-copy-byte-stmt:end:
    22482     # . reclaim locals
    22483     81 0/subop/add %esp 0x6c/imm32
    22484     # . restore registers
    22485     5f/pop-to-edi
    22486     5e/pop-to-esi
    22487     5a/pop-to-edx
    22488     59/pop-to-ecx
    22489     58/pop-to-eax
    22490     # . epilogue
    22491     89/<- %esp 5/r32/ebp
    22492     5d/pop-to-ebp
    22493     c3/return
    22494
    22495 $check-mu-copy-byte-stmt:error-no-inout:
    22496     (write-buffered *(ebp+0x10) "fn ")
    22497     8b/-> *(ebp+0xc) 0/r32/eax
    22498     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22499     (write-buffered *(ebp+0x10) %eax)
    22500     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
    22501     (flush *(ebp+0x10))
    22502     (stop *(ebp+0x14) 1)
    22503     # never gets here
    22504
    22505 $check-mu-copy-byte-stmt:error-too-many-inouts:
    22506     (write-buffered *(ebp+0x10) "fn ")
    22507     8b/-> *(ebp+0xc) 0/r32/eax
    22508     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22509     (write-buffered *(ebp+0x10) %eax)
    22510     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
    22511     (flush *(ebp+0x10))
    22512     (stop *(ebp+0x14) 1)
    22513     # never gets here
    22514
    22515 $check-mu-copy-byte-stmt:error-no-output:
    22516     (write-buffered *(ebp+0x10) "fn ")
    22517     8b/-> *(ebp+0xc) 0/r32/eax
    22518     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22519     (write-buffered *(ebp+0x10) %eax)
    22520     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
    22521     (flush *(ebp+0x10))
    22522     (stop *(ebp+0x14) 1)
    22523     # never gets here
    22524
    22525 $check-mu-copy-byte-stmt:error-output-not-in-register:
    22526     (write-buffered *(ebp+0x10) "fn ")
    22527     8b/-> *(ebp+0xc) 0/r32/eax
    22528     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22529     (write-buffered *(ebp+0x10) %eax)
    22530     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
    22531     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22532     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22533     (write-buffered *(ebp+0x10) %eax)
    22534     (write-buffered *(ebp+0x10) "' not in a register\n")
    22535     (flush *(ebp+0x10))
    22536     (stop *(ebp+0x14) 1)
    22537     # never gets here
    22538
    22539 $check-mu-copy-byte-stmt:error-too-many-outputs:
    22540     (write-buffered *(ebp+0x10) "fn ")
    22541     8b/-> *(ebp+0xc) 0/r32/eax
    22542     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22543     (write-buffered *(ebp+0x10) %eax)
    22544     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
    22545     (flush *(ebp+0x10))
    22546     (stop *(ebp+0x14) 1)
    22547     # never gets here
    22548
    22549 $check-mu-copy-byte-stmt:error-invalid-output-type:
    22550     (write-buffered *(ebp+0x10) "fn ")
    22551     8b/-> *(ebp+0xc) 0/r32/eax
    22552     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22553     (write-buffered *(ebp+0x10) %eax)
    22554     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
    22555     (flush *(ebp+0x10))
    22556     (stop *(ebp+0x14) 1)
    22557     # never gets here
    22558
    22559 $check-mu-copy-byte-stmt:error-inout-too-large:
    22560     (write-buffered *(ebp+0x10) "fn ")
    22561     8b/-> *(ebp+0xc) 0/r32/eax
    22562     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22563     (write-buffered *(ebp+0x10) %eax)
    22564     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
    22565     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22566     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22567     (write-buffered *(ebp+0x10) %eax)
    22568     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22569     (flush *(ebp+0x10))
    22570     (stop *(ebp+0x14) 1)
    22571     # never gets here
    22572
    22573 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22574     # . prologue
    22575     55/push-ebp
    22576     89/<- %ebp 4/r32/esp
    22577     # . save registers
    22578     50/push-eax
    22579     52/push-edx
    22580     53/push-ebx
    22581     56/push-esi
    22582     57/push-edi
    22583     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22584     81 5/subop/subtract %esp 0x60/imm32
    22585     68/push 0x60/imm32/size
    22586     68/push 0/imm32/read
    22587     68/push 0/imm32/write
    22588     89/<- %edx 4/r32/esp
    22589     # esi = stmt
    22590     8b/-> *(ebp+8) 6/r32/esi
    22591 $check-mu-copy-byte-to-stmt:check-for-output:
    22592     # if stmt->outputs abort
    22593     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22594     3d/compare-eax-and 0/imm32
    22595     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
    22596 $check-mu-copy-byte-to-stmt:get-dest:
    22597     # var dest/edi: (addr stmt-var) = stmt->inouts
    22598     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22599     89/<- %edi 0/r32/eax
    22600     # zero inouts
    22601     3d/compare-eax-and 0/imm32
    22602     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22603 $check-mu-copy-byte-to-stmt:get-src:
    22604     # var src/esi: (addr stmt-var) = dest->next
    22605     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22606     89/<- %esi 0/r32/eax
    22607     # 1 inout
    22608     3d/compare-eax-and 0/imm32
    22609     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22610     # > 2 inouts
    22611     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22612     3d/compare-eax-and 0/imm32
    22613     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22614 $check-mu-copy-byte-to-stmt:types:
    22615     # if src is not a scalar, abort
    22616     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22617     (size-of %eax)  # => eax
    22618     3d/compare-eax-and 4/imm32
    22619     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
    22620     # if src not in register, abort
    22621     {
    22622       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22623       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22624       3d/compare-eax-and 0/imm32
    22625       75/jump-if-!= break/disp8
    22626       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
    22627     }
    22628     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22629     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22630     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22631     89/<- %ebx 0/r32/eax
    22632     # if (dest->is-deref?) dest-type = dest-type->payload
    22633 $check-mu-copy-byte-to-stmt:check-dest-deref:
    22634     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22635     3d/compare-eax-and 0/imm32/false
    22636     {
    22637       74/jump-if-= break/disp8
    22638       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22639 $check-mu-copy-byte-to-stmt:dest-is-deref:
    22640       # if dest-type->right is null, dest-type = dest-type->left
    22641       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22642       {
    22643         75/jump-if-!= break/disp8
    22644 $check-mu-copy-byte-to-stmt:dest-is-deref2:
    22645         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22646       }
    22647       89/<- %ebx 0/r32/eax
    22648     }
    22649     # if dest is not a byte, abort
    22650     (simple-mu-type? %ebx 8)  # byte => eax
    22651     3d/compare-eax-and 0/imm32/false
    22652     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
    22653 $check-mu-copy-byte-to-stmt:end:
    22654     # . reclaim locals
    22655     81 0/subop/add %esp 0x6c/imm32
    22656     # . restore registers
    22657     5f/pop-to-edi
    22658     5e/pop-to-esi
    22659     5b/pop-to-ebx
    22660     5a/pop-to-edx
    22661     58/pop-to-eax
    22662     # . epilogue
    22663     89/<- %esp 5/r32/ebp
    22664     5d/pop-to-ebp
    22665     c3/return
    22666
    22667 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
    22668     (write-buffered *(ebp+0x10) "fn ")
    22669     8b/-> *(ebp+0xc) 0/r32/eax
    22670     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22671     (write-buffered *(ebp+0x10) %eax)
    22672     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
    22673     (flush *(ebp+0x10))
    22674     (stop *(ebp+0x14) 1)
    22675     # never gets here
    22676
    22677 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
    22678     (write-buffered *(ebp+0x10) "fn ")
    22679     8b/-> *(ebp+0xc) 0/r32/eax
    22680     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22681     (write-buffered *(ebp+0x10) %eax)
    22682     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
    22683     (flush *(ebp+0x10))
    22684     (stop *(ebp+0x14) 1)
    22685     # never gets here
    22686
    22687 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
    22688     (write-buffered *(ebp+0x10) "fn ")
    22689     8b/-> *(ebp+0xc) 0/r32/eax
    22690     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22691     (write-buffered *(ebp+0x10) %eax)
    22692     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
    22693     (flush *(ebp+0x10))
    22694     (stop *(ebp+0x14) 1)
    22695     # never gets here
    22696
    22697 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
    22698     (write-buffered *(ebp+0x10) "fn ")
    22699     8b/-> *(ebp+0xc) 0/r32/eax
    22700     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22701     (write-buffered *(ebp+0x10) %eax)
    22702     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22703     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22704     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22705     (write-buffered *(ebp+0x10) %eax)
    22706     (write-buffered *(ebp+0x10) "' must be a byte\n")
    22707     (flush *(ebp+0x10))
    22708     (stop *(ebp+0x14) 1)
    22709     # never gets here
    22710
    22711 $check-mu-copy-byte-to-stmt:error-src-too-large:
    22712     (write-buffered *(ebp+0x10) "fn ")
    22713     8b/-> *(ebp+0xc) 0/r32/eax
    22714     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22715     (write-buffered *(ebp+0x10) %eax)
    22716     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22717     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22718     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22719     (write-buffered *(ebp+0x10) %eax)
    22720     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22721     (flush *(ebp+0x10))
    22722     (stop *(ebp+0x14) 1)
    22723     # never gets here
    22724
    22725 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22726     # . prologue
    22727     55/push-ebp
    22728     89/<- %ebp 4/r32/esp
    22729     # . save registers
    22730     50/push-eax
    22731     51/push-ecx
    22732     52/push-edx
    22733     53/push-ebx
    22734     56/push-esi
    22735     57/push-edi
    22736     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22737     81 5/subop/subtract %esp 0x60/imm32
    22738     68/push 0x60/imm32/size
    22739     68/push 0/imm32/read
    22740     68/push 0/imm32/write
    22741     89/<- %edx 4/r32/esp
    22742     # esi = stmt
    22743     8b/-> *(ebp+8) 6/r32/esi
    22744 $check-mu-compare-stmt:check-for-output:
    22745     # if stmt->outputs abort
    22746     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22747     3d/compare-eax-and 0/imm32
    22748     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
    22749 $check-mu-compare-stmt:get-left:
    22750     # var left/edi: (addr stmt-var) = stmt->inouts
    22751     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22752     89/<- %edi 0/r32/eax
    22753     # zero inouts
    22754     3d/compare-eax-and 0/imm32
    22755     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22756 $check-mu-compare-stmt:get-right:
    22757     # var right/esi: (addr stmt-var) = left->next
    22758     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22759     89/<- %esi 0/r32/eax
    22760     # 1 inout
    22761     3d/compare-eax-and 0/imm32
    22762     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22763     # > 2 inouts
    22764     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22765     3d/compare-eax-and 0/imm32
    22766     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22767     # if both inouts are in memory, abort
    22768     {
    22769 $check-mu-compare-stmt:both-in-mem:
    22770       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22771       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22772       (simple-mu-type? %eax 0)  # => eax
    22773       3d/compare-eax-and 0/imm32
    22774       0f 85/jump-if-!= break/disp32
    22775       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22776       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22777       3d/compare-eax-and 0/imm32
    22778       75/jump-if-!= break/disp8
    22779       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22780       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22781       (simple-mu-type? %eax 0)  # => eax
    22782       3d/compare-eax-and 0/imm32
    22783       75/jump-if-!= break/disp8
    22784       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22785       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22786       3d/compare-eax-and 0/imm32
    22787       75/jump-if-!= break/disp8
    22788       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
    22789     }
    22790 $check-mu-compare-stmt:types:
    22791     # var right-type/ecx: (addr type-tree) = right->value->type
    22792     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22793     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22794     89/<- %ecx 0/r32/eax
    22795     # if (right->is-deref?) right-type = right-type->payload
    22796     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22797     3d/compare-eax-and 0/imm32/false
    22798     {
    22799       74/jump-if-= break/disp8
    22800       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22801       # if right-type->right is null, right-type = right-type->left
    22802       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22803       {
    22804         75/jump-if-!= break/disp8
    22805         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22806       }
    22807       89/<- %ecx 0/r32/eax
    22808     }
    22809     # if right-type is a literal string, abort
    22810     (simple-mu-type? %ecx 0x10)  # string-literal => eax
    22811     3d/compare-eax-and 0/imm32/false
    22812     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
    22813     # if right is not a scalar, abort
    22814     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22815     (size-of %eax)  # => eax
    22816     3d/compare-eax-and 4/imm32
    22817     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
    22818     # if left is not a scalar, abort
    22819     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22820     (size-of %eax)  # => eax
    22821     3d/compare-eax-and 4/imm32
    22822     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
    22823     # var left-type/ebx: (addr type-tree) = left->value->type
    22824     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22825     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22826     89/<- %ebx 0/r32/eax
    22827     # if (left->is-deref?) left-type = left-type->payload
    22828     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22829     3d/compare-eax-and 0/imm32/false
    22830     {
    22831       74/jump-if-= break/disp8
    22832       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22833       # if left-type->right is null, left-type = left-type->left
    22834       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22835       {
    22836         75/jump-if-!= break/disp8
    22837         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22838       }
    22839       89/<- %ebx 0/r32/eax
    22840     }
    22841     # if (left-type == right-type) return
    22842     (type-match? %ebx %ecx %edx)  # => eax
    22843     3d/compare-eax-and 0/imm32
    22844     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
    22845     # if left is an addr and right is 0, return
    22846     {
    22847       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22848       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22849       (mu-addr-type? %eax)  # => eax
    22850       3d/compare-eax-and 0/imm32/false
    22851       74/jump-if-= break/disp8
    22852       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22853       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22854       (string-equal? %eax "0")  # => eax
    22855       3d/compare-eax-and 0/imm32/false
    22856       74/jump-if-= break/disp8
    22857       eb/jump $check-mu-compare-stmt:end/disp8
    22858     }
    22859     # if left is not number-like, abort
    22860     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22861 $check-mu-compare-stmt:end:
    22862     # . reclaim locals
    22863     81 0/subop/add %esp 0x6c/imm32
    22864     # . restore registers
    22865     5f/pop-to-edi
    22866     5e/pop-to-esi
    22867     5b/pop-to-ebx
    22868     5a/pop-to-edx
    22869     59/pop-to-ecx
    22870     58/pop-to-eax
    22871     # . epilogue
    22872     89/<- %esp 5/r32/ebp
    22873     5d/pop-to-ebp
    22874     c3/return
    22875
    22876 $check-mu-compare-stmt:error-incorrect-inouts:
    22877     (write-buffered *(ebp+0x10) "fn ")
    22878     8b/-> *(ebp+0xc) 0/r32/eax
    22879     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22880     (write-buffered *(ebp+0x10) %eax)
    22881     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
    22882     (flush *(ebp+0x10))
    22883     (stop *(ebp+0x14) 1)
    22884     # never gets here
    22885
    22886 $check-mu-compare-stmt:error-too-many-outputs:
    22887     (write-buffered *(ebp+0x10) "fn ")
    22888     8b/-> *(ebp+0xc) 0/r32/eax
    22889     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22890     (write-buffered *(ebp+0x10) %eax)
    22891     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
    22892     (flush *(ebp+0x10))
    22893     (stop *(ebp+0x14) 1)
    22894     # never gets here
    22895
    22896 $check-mu-compare-stmt:error-both-in-memory:
    22897     (write-buffered *(ebp+0x10) "fn ")
    22898     8b/-> *(ebp+0xc) 0/r32/eax
    22899     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22900     (write-buffered *(ebp+0x10) %eax)
    22901     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
    22902     (flush *(ebp+0x10))
    22903     (stop *(ebp+0x14) 1)
    22904     # never gets here
    22905
    22906 $check-mu-compare-stmt:error-left-too-large:
    22907     (write-buffered *(ebp+0x10) "fn ")
    22908     8b/-> *(ebp+0xc) 0/r32/eax
    22909     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22910     (write-buffered *(ebp+0x10) %eax)
    22911     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22912     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22913     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22914     (write-buffered *(ebp+0x10) %eax)
    22915     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22916     (flush *(ebp+0x10))
    22917     (stop *(ebp+0x14) 1)
    22918     # never gets here
    22919
    22920 $check-mu-compare-stmt:error-right-too-large:
    22921     (write-buffered *(ebp+0x10) "fn ")
    22922     8b/-> *(ebp+0xc) 0/r32/eax
    22923     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22924     (write-buffered *(ebp+0x10) %eax)
    22925     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22926     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22927     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22928     (write-buffered *(ebp+0x10) %eax)
    22929     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22930     (flush *(ebp+0x10))
    22931     (stop *(ebp+0x14) 1)
    22932     # never gets here
    22933
    22934 $check-mu-compare-stmt:error-right-string-literal:
    22935     (write-buffered *(ebp+0x10) "fn ")
    22936     8b/-> *(ebp+0xc) 0/r32/eax
    22937     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22938     (write-buffered *(ebp+0x10) %eax)
    22939     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
    22940     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22941     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22942     (write-buffered *(ebp+0x10) %eax)
    22943     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
    22944     (flush *(ebp+0x10))
    22945     (stop *(ebp+0x14) 1)
    22946     # never gets here
    22947
    22948 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22949     # . prologue
    22950     55/push-ebp
    22951     89/<- %ebp 4/r32/esp
    22952     # . save registers
    22953     50/push-eax
    22954     51/push-ecx
    22955     52/push-edx
    22956     56/push-esi
    22957     57/push-edi
    22958 $check-mu-address-stmt:get-output:
    22959     # esi = stmt
    22960     8b/-> *(ebp+8) 6/r32/esi
    22961     # var output/edi: (addr stmt-var) = stmt->outputs
    22962     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22963     89/<- %edi 0/r32/eax
    22964     # zero outputs
    22965     3d/compare-eax-and 0/imm32
    22966     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
    22967     # > 1 output
    22968     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22969     3d/compare-eax-and 0/imm32
    22970     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
    22971 $check-mu-address-stmt:get-inout:
    22972     # var inout/esi: (addr stmt-var) = stmt->inouts
    22973     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22974     89/<- %esi 0/r32/eax
    22975     # zero inouts
    22976     3d/compare-eax-and 0/imm32
    22977     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
    22978     # > 1 inout
    22979     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22980     3d/compare-eax-and 0/imm32
    22981     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
    22982 $check-mu-address-stmt:types:
    22983     # if output not in register, abort
    22984     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22985     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22986     3d/compare-eax-and 0/imm32
    22987     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
    22988     # var output-type/edx: (addr type-tree) = output->value->type
    22989     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22990     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22991     89/<- %edx 0/r32/eax
    22992     # if output-type not an addr, abort
    22993     (mu-addr-type? %edx)  # => eax
    22994     3d/compare-eax-and 0/imm32/false
    22995     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
    22996     # output-type = output-type->right
    22997     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    22998     # if output-type->right is null, output-type = output-type->left
    22999     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23000     {
    23001       75/jump-if-!= break/disp8
    23002       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23003     }
    23004     89/<- %edx 0/r32/eax
    23005     # var inout-type/ecx: (addr type-tree) = inout->value->type
    23006     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23007     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23008     89/<- %ecx 0/r32/eax
    23009     # if (inout->is-deref?) inout-type = inout-type->payload
    23010     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    23011     3d/compare-eax-and 0/imm32/false
    23012     {
    23013       74/jump-if-= break/disp8
    23014       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23015       # if inout-type->right is null, t = inout-type->left
    23016       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23017       {
    23018         75/jump-if-!= break/disp8
    23019         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23020       }
    23021       89/<- %ecx 0/r32/eax
    23022     }
    23023     # if (inout-type != output-type) abort
    23024     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
    23025     3d/compare-eax-and 0/imm32
    23026     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
    23027 $check-mu-address-stmt:end:
    23028     # . restore registers
    23029     5f/pop-to-edi
    23030     5e/pop-to-esi
    23031     5a/pop-to-edx
    23032     59/pop-to-ecx
    23033     58/pop-to-eax
    23034     # . epilogue
    23035     89/<- %esp 5/r32/ebp
    23036     5d/pop-to-ebp
    23037     c3/return
    23038
    23039 $check-mu-address-stmt:error-no-inout:
    23040     (write-buffered *(ebp+0x10) "fn ")
    23041     8b/-> *(ebp+0xc) 0/r32/eax
    23042     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23043     (write-buffered *(ebp+0x10) %eax)
    23044     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
    23045     (flush *(ebp+0x10))
    23046     (stop *(ebp+0x14) 1)
    23047     # never gets here
    23048
    23049 $check-mu-address-stmt:error-too-many-inouts:
    23050     (write-buffered *(ebp+0x10) "fn ")
    23051     8b/-> *(ebp+0xc) 0/r32/eax
    23052     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23053     (write-buffered *(ebp+0x10) %eax)
    23054     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
    23055     (flush *(ebp+0x10))
    23056     (stop *(ebp+0x14) 1)
    23057     # never gets here
    23058
    23059 $check-mu-address-stmt:error-no-output:
    23060     (write-buffered *(ebp+0x10) "fn ")
    23061     8b/-> *(ebp+0xc) 0/r32/eax
    23062     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23063     (write-buffered *(ebp+0x10) %eax)
    23064     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
    23065     (flush *(ebp+0x10))
    23066     (stop *(ebp+0x14) 1)
    23067     # never gets here
    23068
    23069 $check-mu-address-stmt:error-output-not-in-register:
    23070     (write-buffered *(ebp+0x10) "fn ")
    23071     8b/-> *(ebp+0xc) 0/r32/eax
    23072     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23073     (write-buffered *(ebp+0x10) %eax)
    23074     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23075     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23076     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23077     (write-buffered *(ebp+0x10) %eax)
    23078     (write-buffered *(ebp+0x10) "' not in a register\n")
    23079     (flush *(ebp+0x10))
    23080     (stop *(ebp+0x14) 1)
    23081     # never gets here
    23082
    23083 $check-mu-address-stmt:error-too-many-outputs:
    23084     (write-buffered *(ebp+0x10) "fn ")
    23085     8b/-> *(ebp+0xc) 0/r32/eax
    23086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23087     (write-buffered *(ebp+0x10) %eax)
    23088     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
    23089     (flush *(ebp+0x10))
    23090     (stop *(ebp+0x14) 1)
    23091     # never gets here
    23092
    23093 $check-mu-address-stmt:error-output-not-address:
    23094     (write-buffered *(ebp+0x10) "fn ")
    23095     8b/-> *(ebp+0xc) 0/r32/eax
    23096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23097     (write-buffered *(ebp+0x10) %eax)
    23098     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23099     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23100     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23101     (write-buffered *(ebp+0x10) %eax)
    23102     (write-buffered *(ebp+0x10) "' is not an addr\n")
    23103     (flush *(ebp+0x10))
    23104     (stop *(ebp+0x14) 1)
    23105     # never gets here
    23106
    23107 $check-mu-address-stmt:error-type-mismatch:
    23108     (write-buffered *(ebp+0x10) "fn ")
    23109     8b/-> *(ebp+0xc) 0/r32/eax
    23110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23111     (write-buffered *(ebp+0x10) %eax)
    23112     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23113     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23114     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23115     (write-buffered *(ebp+0x10) %eax)
    23116     (write-buffered *(ebp+0x10) "' cannot hold address of '")
    23117     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23118     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23119     (write-buffered *(ebp+0x10) %eax)
    23120     (write-buffered *(ebp+0x10) "'\n")
    23121     (flush *(ebp+0x10))
    23122     (stop *(ebp+0x14) 1)
    23123     # never gets here
    23124
    23125 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    23126     # . prologue
    23127     55/push-ebp
    23128     89/<- %ebp 4/r32/esp
    23129     # . save registers
    23130     51/push-ecx
    23131     52/push-edx
    23132     53/push-ebx
    23133     # var curr-a/ecx: (addr type-tree) = a
    23134     8b/-> *(ebp+8) 1/r32/ecx
    23135     # var curr-b/ebx: (addr type-tree) = b
    23136     8b/-> *(ebp+0xc) 3/r32/ebx
    23137     # if (curr-a->is-atom?) fall back to regular equality
    23138     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    23139     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
    23140     # if (curr-a->left != curr-b->left) return false
    23141     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    23142     89/<- %edx 0/r32/eax
    23143     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23144     (type-equal? %edx %eax)  # => eax
    23145     3d/compare-eax-and 0/imm32/false
    23146     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
    23147     # if (curr-a->left == "array") curr-a = curr-a->element-type
    23148     {
    23149       (mu-array? %edx)  # => eax
    23150       3d/compare-eax-and 0/imm32/false
    23151       75/jump-if-!= break/disp8
    23152 $type-equal-ignoring-capacity?:array:
    23153       # curr-a = curr-a->right->left
    23154       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23155       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23156       89/<- %ecx 0/r32/eax
    23157       # curr-b = curr-b->right->left
    23158       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23159       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23160       89/<- %ebx 0/r32/eax
    23161       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23162     }
    23163     # if (curr-a->left == "stream") curr-a = curr-a->element-type
    23164     {
    23165       (mu-stream? %edx)  # => eax
    23166       3d/compare-eax-and 0/imm32/false
    23167       75/jump-if-!= break/disp8
    23168 $type-equal-ignoring-capacity?:stream:
    23169       # curr-a = curr-a->right->left
    23170       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23171       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23172       89/<- %ecx 0/r32/eax
    23173       # curr-b = curr-b->right->left
    23174       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23175       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23176       89/<- %ebx 0/r32/eax
    23177       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23178     }
    23179 $type-equal-ignoring-capacity?:base-case:
    23180     # return type-equal?(curr-a, curr-b)
    23181     (type-equal? %ecx %ebx)  # => eax
    23182 $type-equal-ignoring-capacity?:end:
    23183     # . restore registers
    23184     5b/pop-to-ebx
    23185     5a/pop-to-edx
    23186     59/pop-to-ecx
    23187     # . epilogue
    23188     89/<- %esp 5/r32/ebp
    23189     5d/pop-to-ebp
    23190     c3/return
    23191
    23192 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23193     # . prologue
    23194     55/push-ebp
    23195     89/<- %ebp 4/r32/esp
    23196     # . save registers
    23197     50/push-eax
    23198     51/push-ecx
    23199     52/push-edx
    23200     53/push-ebx
    23201     56/push-esi
    23202     57/push-edi
    23203     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    23204     81 5/subop/subtract %esp 0x60/imm32
    23205     68/push 0x60/imm32/size
    23206     68/push 0/imm32/read
    23207     68/push 0/imm32/write
    23208     89/<- %edx 4/r32/esp
    23209     # var template/esi: (addr list var) = fn->outputs
    23210     8b/-> *(ebp+0xc) 0/r32/eax
    23211     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    23212     89/<- %esi 0/r32/eax
    23213     # var curr-template/ebx: (addr list var) = fn->outputs
    23214     89/<- %ebx 0/r32/eax
    23215     # var curr/edi: (addr stmt-var) = stmt->inouts
    23216     8b/-> *(ebp+8) 0/r32/eax
    23217     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23218     89/<- %edi 0/r32/eax
    23219     {
    23220       # if template is null, break
    23221       81 7/subop/compare %ebx 0/imm32
    23222       0f 84/jump-if-= break/disp32
    23223       # if curr is null, abort
    23224       81 7/subop/compare %edi 0/imm32
    23225       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
    23226       # var template-type/ecx: (addr type-tree) = template->value->type
    23227       (lookup *ebx *(ebx+4))  # List-value List-value => eax
    23228       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23229       89/<- %ecx 0/r32/eax
    23230       # var curr-type/eax: (addr type-tree) = curr->value->type
    23231       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23232       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23233       # if (curr->is-deref?) curr-type = payload of curr-type
    23234       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
    23235       {
    23236         74/jump-if-= break/disp8
    23237         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23238         # if t->right is null, t = t->left
    23239         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23240         75/jump-if-!= break/disp8
    23241         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23242       }
    23243       # if curr-type is literal and template-type is float, abort
    23244       50/push-eax
    23245       {
    23246         (simple-mu-type? %eax 0)  # literal => eax
    23247         3d/compare-eax-and 0/imm32/false
    23248         74/jump-if-= break/disp8
    23249         (simple-mu-type? %ecx 0xf)  # float => eax
    23250         3d/compare-eax-and 0/imm32/false
    23251         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
    23252       }
    23253       58/pop-to-eax
    23254       # if (curr-type != template-type) abort
    23255       (type-match? %ecx %eax %edx)  # => eax
    23256       3d/compare-eax-and 0/imm32/false
    23257       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
    23258       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
    23259       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
    23260       3d/compare-eax-and 0/imm32/false
    23261       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
    23262       # template = template->next
    23263       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
    23264       89/<- %ebx 0/r32/eax
    23265       # curr = curr->next
    23266       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23267       89/<- %edi 0/r32/eax
    23268       #
    23269       e9/jump loop/disp32
    23270     }
    23271     # if curr is not null, abort
    23272     81 7/subop/compare %edi 0/imm32
    23273     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
    23274 $check-mu-return-stmt:end:
    23275     # . reclaim locals
    23276     81 0/subop/add %esp 0x6c/imm32
    23277     # . restore registers
    23278     5f/pop-to-edi
    23279     5e/pop-to-esi
    23280     5b/pop-to-ebx
    23281     5a/pop-to-edx
    23282     59/pop-to-ecx
    23283     58/pop-to-eax
    23284     # . epilogue
    23285     89/<- %esp 5/r32/ebp
    23286     5d/pop-to-ebp
    23287     c3/return
    23288
    23289 $check-mu-return-stmt:error1:
    23290     (write-buffered *(ebp+0x10) "fn ")
    23291     8b/-> *(ebp+0xc) 0/r32/eax
    23292     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23293     (write-buffered *(ebp+0x10) %eax)
    23294     (write-buffered *(ebp+0x10) ": return: '")
    23295     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23296     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23297     (write-buffered *(ebp+0x10) %eax)
    23298     (write-buffered *(ebp+0x10) "' has the wrong type\n")
    23299     (flush *(ebp+0x10))
    23300     (stop *(ebp+0x14) 1)
    23301     # never gets here
    23302
    23303 $check-mu-return-stmt:error2:
    23304     (write-buffered *(ebp+0x10) "fn ")
    23305     8b/-> *(ebp+0xc) 0/r32/eax
    23306     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23307     (write-buffered *(ebp+0x10) %eax)
    23308     (write-buffered *(ebp+0x10) ": return: '")
    23309     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23310     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23311     (write-buffered *(ebp+0x10) %eax)
    23312     (write-buffered *(ebp+0x10) "' is no longer available\n")
    23313     (flush *(ebp+0x10))
    23314     (stop *(ebp+0x14) 1)
    23315     # never gets here
    23316
    23317 $check-mu-return-stmt:error-literal-to-float:
    23318     (write-buffered *(ebp+0x10) "fn ")
    23319     8b/-> *(ebp+0xc) 0/r32/eax
    23320     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23321     (write-buffered *(ebp+0x10) %eax)
    23322     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
    23323     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23324     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23325     (write-buffered *(ebp+0x10) %eax)
    23326     (write-buffered *(ebp+0x10) "' to float\n")
    23327     (flush *(ebp+0x10))
    23328     (stop *(ebp+0x14) 1)
    23329     # never gets here
    23330
    23331 $check-mu-return-stmt:error-too-few-inouts:
    23332     (write-buffered *(ebp+0x10) "fn ")
    23333     8b/-> *(ebp+0xc) 0/r32/eax
    23334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23335     (write-buffered *(ebp+0x10) %eax)
    23336     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
    23337     (flush *(ebp+0x10))
    23338     (stop *(ebp+0x14) 1)
    23339     # never gets here
    23340
    23341 $check-mu-return-stmt:error-too-many-inouts:
    23342     (write-buffered *(ebp+0x10) "fn ")
    23343     8b/-> *(ebp+0xc) 0/r32/eax
    23344     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23345     (write-buffered *(ebp+0x10) %eax)
    23346     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
    23347     (flush *(ebp+0x10))
    23348     (stop *(ebp+0x14) 1)
    23349     # never gets here
    23350
    23351 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23352     # . prologue
    23353     55/push-ebp
    23354     89/<- %ebp 4/r32/esp
    23355     # . save registers
    23356     50/push-eax
    23357     51/push-ecx
    23358     56/push-esi
    23359     # var table/esi: (addr table (handle array byte) int 8)
    23360     81 5/subop/subtract %esp 0x60/imm32
    23361     68/push 0x60/imm32/size
    23362     68/push 0/imm32/read
    23363     68/push 0/imm32/write
    23364     89/<- %esi 4/r32/esp
    23365     # var curr/ecx: (addr list var) = outputs
    23366     8b/-> *(ebp+8) 1/r32/ecx
    23367     {
    23368       # if (curr == 0) break
    23369       81 7/subop/compare %ecx 0/imm32
    23370       0f 84/jump-if-= break/disp32
    23371       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
    23372       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23373       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23374       # if reg exists in table, abort
    23375       (maybe-get %esi %eax 0xc)  # => eax
    23376       3d/compare-eax-and 0/imm32
    23377       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
    23378       # insert reg in table
    23379       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23380       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23381       (get-or-insert %esi %eax 0xc Heap)
    23382       # curr = curr->next
    23383       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23384       89/<- %ecx 0/r32/eax
    23385       e9/jump loop/disp32
    23386     }
    23387 $check-all-unique-registers:end:
    23388     # . reclaim locals
    23389     81 0/subop/add %esp 0x6c/imm32
    23390     # . restore registers
    23391     5e/pop-to-esi
    23392     59/pop-to-ecx
    23393     58/pop-to-eax
    23394     # . epilogue
    23395     89/<- %esp 5/r32/ebp
    23396     5d/pop-to-ebp
    23397     c3/return
    23398
    23399 $check-all-unique-registers:abort:
    23400     (write-buffered *(ebp+0x10) "fn ")
    23401     8b/-> *(ebp+0xc) 0/r32/eax
    23402     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23403     (write-buffered *(ebp+0x10) %eax)
    23404     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
    23405     (flush *(ebp+0x10))
    23406     (stop *(ebp+0x14) 1)
    23407     # never gets here
    23408
    23409 # return false if s's register is not between start (inclusive) and end (exclusive)
    23410 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
    23411 # otherwise return true
    23412 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
    23413     # . prologue
    23414     55/push-ebp
    23415     89/<- %ebp 4/r32/esp
    23416     # . save registers
    23417     51/push-ecx
    23418     52/push-edx
    23419     53/push-ebx
    23420     56/push-esi
    23421     57/push-edi
    23422     # var target/ebx: (addr array byte) = s->value->register
    23423     8b/-> *(ebp+8) 0/r32/eax
    23424     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23425     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23426 #?     (write-buffered Stderr "AA: ")
    23427 #?     (write-buffered Stderr %eax)
    23428 #?     (write-buffered Stderr Newline)
    23429 #?     (flush Stderr)
    23430     # if (var->register == 0) return false
    23431     3d/compare-eax-and 0/imm32
    23432     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
    23433     89/<- %ebx 0/r32/eax
    23434     # var curr/ecx: (addr list var) = start
    23435     8b/-> *(ebp+0xc) 1/r32/ecx
    23436     # edx = end
    23437     8b/-> *(ebp+0x10) 2/r32/edx
    23438     {
    23439       # if (curr == 0) break
    23440       81 7/subop/compare %edi 0/imm32
    23441       0f 84/jump-if-= break/disp32
    23442       # if (curr == end) break
    23443       39/compare %ecx 2/r32/edx
    23444       0f 84/jump-if-= break/disp32
    23445       # var curr-reg/eax: (addr array byte) = curr->value->register
    23446       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23447       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23448       # if (curr-reg == 0) continue
    23449       3d/compare-eax-and 0/imm32
    23450       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
    23451       # if (curr-reg == target) check for conflict
    23452       (string-equal? %eax %ebx)  # => eax
    23453       3d/compare-eax-and 0/imm32/false
    23454       {
    23455         74/jump-if-= break/disp8
    23456 #?         (write-buffered Stderr "conflict?\n")
    23457 #?         (flush Stderr)
    23458         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
    23459         8b/-> *(ebp+0x14) 0/r32/eax
    23460         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23461         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
    23462         eb/jump $register-within-list-with-conflict?:end/disp8
    23463       }
    23464 $register-within-list-with-conflict?:continue:
    23465       # curr = curr->next
    23466       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23467       89/<- %ecx 0/r32/eax
    23468       e9/jump loop/disp32
    23469     }
    23470     # return false
    23471     b8/copy-to-eax 0/imm32/false
    23472 $register-within-list-with-conflict?:end:
    23473     # . restore registers
    23474     5f/pop-to-edi
    23475     5e/pop-to-esi
    23476     5b/pop-to-ebx
    23477     5a/pop-to-edx
    23478     59/pop-to-ecx
    23479     # . epilogue
    23480     89/<- %esp 5/r32/ebp
    23481     5d/pop-to-ebp
    23482     c3/return
    23483
    23484 # At the first occurrence of register 'reg' in fn-outputs,
    23485 # check if the corresponding element of return-inouts has a different register.
    23486 # This hacky helper is intended to be called in one specific place. Don't
    23487 # reuse it as is.
    23488 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
    23489     # . prologue
    23490     55/push-ebp
    23491     89/<- %ebp 4/r32/esp
    23492     # . save registers
    23493     51/push-ecx
    23494     52/push-edx
    23495     53/push-ebx
    23496     56/push-esi
    23497     57/push-edi
    23498 #?     (write-buffered Stderr "BB: ")
    23499 #?     (write-buffered Stderr *(ebp+8))
    23500 #?     (write-buffered Stderr Newline)
    23501 #?     (flush Stderr)
    23502     # var curr-output/edi: (addr list var) = fn-outputs
    23503     8b/-> *(ebp+0x10) 7/r32/edi
    23504     # var curr-inout/esi: (addr stmt-var) = return-inouts
    23505     8b/-> *(ebp+0xc) 6/r32/esi
    23506     {
    23507       # if (curr-output == 0) abort
    23508       81 7/subop/compare %edi 0/imm32
    23509       0f 84/jump-if-= break/disp32
    23510       # if (curr-output->value->register != reg) continue
    23511       (lookup *edi *(edi+4))  # List-value List-value => eax
    23512       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23513       (string-equal? %eax *(ebp+8))  # => eax
    23514       3d/compare-eax-and 0/imm32/false
    23515       0f 84/jump-if= $register-conflict?:continue/disp32
    23516 #?       (write-buffered Stderr "rescan\n")
    23517 #?       (flush Stderr)
    23518       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
    23519       (lookup *esi *(esi+4))  # List-value List-value => eax
    23520       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23521       # if (curr-reg == 0) return true
    23522       3d/compare-eax-and 0/imm32
    23523       {
    23524         75/jump-if-!= break/disp8
    23525 #?         (write-buffered Stderr "no register\n")
    23526 #?         (flush Stderr)
    23527         b8/copy-to-eax 1/imm32/true
    23528         e9/jump $register-conflict?:end/disp32
    23529       }
    23530       # return (curr-reg != reg)
    23531       (string-equal? %eax *(ebp+8))  # => eax
    23532       3d/compare-eax-and 0/imm32/false
    23533       0f 94/set-if-= %al
    23534 #?       (write-buffered Stderr "final: ")
    23535 #?       (write-int32-hex-buffered Stderr %eax)
    23536 #?       (write-buffered Stderr Newline)
    23537 #?       (flush Stderr)
    23538       eb/jump $register-conflict?:end/disp8
    23539 $register-conflict?:continue:
    23540       # curr-output = curr-output->next
    23541       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    23542       89/<- %edi 0/r32/eax
    23543       # curr-inout = curr-inout->next
    23544       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23545       89/<- %esi 0/r32/eax
    23546       e9/jump loop/disp32
    23547     }
    23548     # should never get here
    23549     (write-buffered Stderr "register-conflict? misused\n")
    23550     (flush Stderr)
    23551     e8/call syscall_exit/disp32
    23552 $register-conflict?:end:
    23553     # . restore registers
    23554     5f/pop-to-edi
    23555     5e/pop-to-esi
    23556     5b/pop-to-ebx
    23557     5a/pop-to-edx
    23558     59/pop-to-ecx
    23559     # . epilogue
    23560     89/<- %esp 5/r32/ebp
    23561     5d/pop-to-ebp
    23562     c3/return
    23563
    23564 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23565     # . prologue
    23566     55/push-ebp
    23567     89/<- %ebp 4/r32/esp
    23568     # . save registers
    23569     50/push-eax
    23570     51/push-ecx
    23571     # var curr/ecx: (addr list stmt) = block->stmts
    23572     8b/-> *(ebp+8) 0/r32/eax
    23573     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23574     3d/compare-eax-and 0/imm32
    23575     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23576     89/<- %ecx 0/r32/eax
    23577     {
    23578       # if curr->next == 0, break
    23579       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23580       3d/compare-eax-and 0/imm32
    23581       74/jump-if-= break/disp8
    23582       # curr = curr->next
    23583       89/<- %ecx 0/r32/eax
    23584       e9/jump loop/disp32
    23585     }
    23586 $check-final-stmt-is-return:check-tag:
    23587     # if curr->value->tag != Stmt1, abort
    23588     (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23589     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23590     75/jump-if-!= $check-final-stmt-is-return:error/disp8
    23591 $check-final-stmt-is-return:check-operation:
    23592     # if curr->operation != "return", abort
    23593     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23594     (string-equal? %eax "return")
    23595     3d/compare-eax-and 0/imm32/false
    23596     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23597 $check-final-stmt-is-return:end:
    23598     # . restore registers
    23599     59/pop-to-ecx
    23600     58/pop-to-eax
    23601     # . epilogue
    23602     89/<- %esp 5/r32/ebp
    23603     5d/pop-to-ebp
    23604     c3/return
    23605
    23606 $check-final-stmt-is-return:error:
    23607     (write-buffered *(ebp+0x10) "fn ")
    23608     8b/-> *(ebp+0xc) 0/r32/eax
    23609     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23610     (write-buffered *(ebp+0x10) %eax)
    23611     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
    23612     (flush *(ebp+0x10))
    23613     (stop *(ebp+0x14) 1)
    23614     # never gets here
    23615
    23616 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23617     # . prologue
    23618     55/push-ebp
    23619     89/<- %ebp 4/r32/esp
    23620     # . save registers
    23621     50/push-eax
    23622     51/push-ecx
    23623     # var curr/ecx: (addr list stmt) = block->stmts
    23624     8b/-> *(ebp+8) 0/r32/eax
    23625     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23626     3d/compare-eax-and 0/imm32
    23627     0f 84/jump-if-= $check-no-breaks:end/disp32
    23628     89/<- %ecx 0/r32/eax
    23629     {
    23630       # if curr->next == 0, break
    23631       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23632       3d/compare-eax-and 0/imm32
    23633       74/jump-if-= break/disp8
    23634       # if curr->value->tag != Stmt1, continue
    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-no-breaks:continue/disp8
    23638       # if curr->value->operation starts with "break", abort
    23639       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23640       (string-starts-with? %eax "break")  # => eax
    23641       3d/compare-eax-and 0/imm32/false
    23642       75/jump-if-!= $check-no-breaks:error/disp8
    23643 $check-no-breaks:continue:
    23644       # curr = curr->next
    23645       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23646       89/<- %ecx 0/r32/eax
    23647       e9/jump loop/disp32
    23648     }
    23649 $check-no-breaks:end:
    23650     # . restore registers
    23651     59/pop-to-ecx
    23652     58/pop-to-eax
    23653     # . epilogue
    23654     89/<- %esp 5/r32/ebp
    23655     5d/pop-to-ebp
    23656     c3/return
    23657
    23658 $check-no-breaks:error:
    23659     (write-buffered *(ebp+0x10) "fn ")
    23660     8b/-> *(ebp+0xc) 0/r32/eax
    23661     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23662     (write-buffered *(ebp+0x10) %eax)
    23663     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
    23664     (flush *(ebp+0x10))
    23665     (stop *(ebp+0x14) 1)
    23666     # never gets here
    23667
    23668 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23669     # . prologue
    23670     55/push-ebp
    23671     89/<- %ebp 4/r32/esp
    23672     # . save registers
    23673     50/push-eax
    23674     51/push-ecx
    23675     52/push-edx
    23676     53/push-ebx
    23677     56/push-esi
    23678     57/push-edi
    23679     # esi = stmt
    23680     8b/-> *(ebp+8) 6/r32/esi
    23681     # - check for 0 inouts
    23682     # var base/ecx: (addr var) = stmt->inouts->value
    23683     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23684     3d/compare-eax-and 0/imm32/false
    23685     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23686     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23687     89/<- %ecx 0/r32/eax
    23688 $check-mu-get-stmt:check-base:
    23689     # - check base type
    23690     # if it's an 'addr', check that it's in a register
    23691     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    23692     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    23693     89/<- %ebx 0/r32/eax
    23694     {
    23695       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23696       0f 85/jump-if-!= break/disp32
    23697 $check-mu-get-stmt:base-is-compound:
    23698       # if (type->left != addr) break
    23699       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23700       (simple-mu-type? %eax 2)  # addr => eax
    23701       3d/compare-eax-and 0/imm32/false
    23702       74/jump-if-= break/disp8
    23703 $check-mu-get-stmt:base-is-addr:
    23704       # now check for register
    23705       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    23706       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
    23707 $check-mu-get-stmt:base-is-addr-in-register:
    23708       # type->left is now an addr; skip it
    23709       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23710       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23711       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
    23712 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
    23713       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23714       89/<- %ebx 0/r32/eax
    23715     }
    23716 $check-mu-get-stmt:check-base-typeinfo:
    23717     # ensure type is a container
    23718     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23719     {
    23720       75/jump-if-!= break/disp8
    23721       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23722       89/<- %ebx 0/r32/eax
    23723     }
    23724     # var base-type-id/ebx: type-id = base-type->value
    23725     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
    23726     (container? %ebx)  # => eax
    23727     3d/compare-eax-and 0/imm32/false
    23728     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
    23729     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
    23730     # . var container/ecx: (handle typeinfo)
    23731     68/push 0/imm32
    23732     68/push 0/imm32
    23733     89/<- %ecx 4/r32/esp
    23734     # .
    23735     (find-typeinfo %ebx %ecx)
    23736     (lookup *ecx *(ecx+4))  # => eax
    23737     # . reclaim container
    23738     81 0/subop/add %esp 8/imm32
    23739     # .
    23740     89/<- %edx 0/r32/eax
    23741     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
    23742     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23743     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23744     89/<- %ecx 0/r32/eax
    23745     # - check for 1 inout
    23746     3d/compare-eax-and 0/imm32/false
    23747     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23748     # var offset/ecx: (addr var) = lookup(offset->value)
    23749     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    23750     89/<- %ecx 0/r32/eax
    23751     # - check for valid field
    23752     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
    23753     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
    23754     # - check for too many inouts
    23755     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23756     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23757     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23758     3d/compare-eax-and 0/imm32/false
    23759     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
    23760     # var output/edi: (addr var) = stmt->outputs->value
    23761     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23762     # - check for 0 outputs
    23763     3d/compare-eax-and 0/imm32/false
    23764     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
    23765     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23766     89/<- %edi 0/r32/eax
    23767 $check-mu-get-stmt:check-output-type:
    23768     # - check output type
    23769     # must be in register
    23770     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    23771     3d/compare-eax-and 0/imm32
    23772     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
    23773     # must have a non-atomic type
    23774     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23775     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    23776     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
    23777     # type must start with (addr ...)
    23778     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23779     (simple-mu-type? %eax 2)  # => eax
    23780     3d/compare-eax-and 0/imm32/false
    23781     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
    23782 $check-mu-get-stmt:check-output-type-match:
    23783     # payload of addr type must match 'type' definition
    23784     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23785     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23786     # if (payload->right == null) payload = payload->left
    23787     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
    23788     {
    23789       75/jump-if-!= break/disp8
    23790       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23791     }
    23792     89/<- %edi 0/r32/eax
    23793     # . var output-name/ecx: (addr array byte)
    23794     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23795     89/<- %ecx 0/r32/eax
    23796     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
    23797     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
    23798     (get %eax %ecx 0x10)  # => eax
    23799     # .
    23800     (lookup *eax *(eax+4))  # => eax
    23801     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    23802     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23803     # .
    23804     (type-equal? %edi %eax)  # => eax
    23805     3d/compare-eax-and 0/imm32/false
    23806     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
    23807     # - check for too many outputs
    23808     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23809     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23810     3d/compare-eax-and 0/imm32/false
    23811     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
    23812 $check-mu-get-stmt:end:
    23813     # . restore registers
    23814     5f/pop-to-edi
    23815     5e/pop-to-esi
    23816     5b/pop-to-ebx
    23817     5a/pop-to-edx
    23818     59/pop-to-ecx
    23819     58/pop-to-eax
    23820     # . epilogue
    23821     89/<- %esp 5/r32/ebp
    23822     5d/pop-to-ebp
    23823     c3/return
    23824
    23825 $check-mu-get-stmt:error-too-few-inouts:
    23826     (write-buffered *(ebp+0x10) "fn ")
    23827     8b/-> *(ebp+0xc) 0/r32/eax
    23828     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23829     (write-buffered *(ebp+0x10) %eax)
    23830     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
    23831     (flush *(ebp+0x10))
    23832     (stop *(ebp+0x14) 1)
    23833     # never gets here
    23834
    23835 $check-mu-get-stmt:error-too-many-inouts:
    23836     (write-buffered *(ebp+0x10) "fn ")
    23837     8b/-> *(ebp+0xc) 0/r32/eax
    23838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23839     (write-buffered *(ebp+0x10) %eax)
    23840     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
    23841     (flush *(ebp+0x10))
    23842     (stop *(ebp+0x14) 1)
    23843     # never gets here
    23844
    23845 $check-mu-get-stmt:error-too-few-outputs:
    23846     (write-buffered *(ebp+0x10) "fn ")
    23847     8b/-> *(ebp+0xc) 0/r32/eax
    23848     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23849     (write-buffered *(ebp+0x10) %eax)
    23850     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
    23851     (flush *(ebp+0x10))
    23852     (stop *(ebp+0x14) 1)
    23853     # never gets here
    23854
    23855 $check-mu-get-stmt:error-too-many-outputs:
    23856     (write-buffered *(ebp+0x10) "fn ")
    23857     8b/-> *(ebp+0xc) 0/r32/eax
    23858     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23859     (write-buffered *(ebp+0x10) %eax)
    23860     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
    23861     (flush *(ebp+0x10))
    23862     (stop *(ebp+0x14) 1)
    23863     # never gets here
    23864
    23865 $check-mu-get-stmt:error-bad-base:
    23866     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
    23867     (write-buffered *(ebp+0x10) "fn ")
    23868     8b/-> *(ebp+0xc) 0/r32/eax
    23869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23870     (write-buffered *(ebp+0x10) %eax)
    23871     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23872     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23873     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23874     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23875     (write-buffered *(ebp+0x10) %eax)
    23876     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
    23877     (flush *(ebp+0x10))
    23878     (stop *(ebp+0x14) 1)
    23879     # never gets here
    23880
    23881 $check-mu-get-stmt:error-base-type-addr-but-not-register:
    23882     (write-buffered *(ebp+0x10) "fn ")
    23883     8b/-> *(ebp+0xc) 0/r32/eax
    23884     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23885     (write-buffered *(ebp+0x10) %eax)
    23886     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23887     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23888     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23889     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23890     (write-buffered *(ebp+0x10) %eax)
    23891     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
    23892     (flush *(ebp+0x10))
    23893     (stop *(ebp+0x14) 1)
    23894     # never gets here
    23895
    23896 $check-mu-get-stmt:error-bad-field:
    23897     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
    23898     (write-buffered *(ebp+0x10) "fn ")
    23899     8b/-> *(ebp+0xc) 0/r32/eax
    23900     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23901     (write-buffered *(ebp+0x10) %eax)
    23902     (write-buffered *(ebp+0x10) ": stmt get: type '")
    23903     # . write(Type-id->data[tmp])
    23904     bf/copy-to-edi Type-id/imm32
    23905     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    23906     {
    23907       81 7/subop/compare %esi 0/imm32
    23908       74/jump-if-= break/disp8
    23909       (write-buffered *(ebp+0x10) %esi)
    23910     }
    23911     # .
    23912     (write-buffered *(ebp+0x10) "' has no member called '")
    23913     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23914     (write-buffered *(ebp+0x10) %eax)
    23915     (write-buffered *(ebp+0x10) "'\n")
    23916     (flush *(ebp+0x10))
    23917     (stop *(ebp+0x14) 1)
    23918     # never gets here
    23919
    23920 $check-mu-get-stmt:error-output-not-in-register:
    23921     (write-buffered *(ebp+0x10) "fn ")
    23922     8b/-> *(ebp+0xc) 0/r32/eax
    23923     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23924     (write-buffered *(ebp+0x10) %eax)
    23925     (write-buffered *(ebp+0x10) ": stmt get: output '")
    23926     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    23927     (write-buffered *(ebp+0x10) %eax)
    23928     (write-buffered *(ebp+0x10) "' is not in a register\n")
    23929     (flush *(ebp+0x10))
    23930     (stop *(ebp+0x14) 1)
    23931     # never gets here
    23932
    23933 $check-mu-get-stmt:error-output-type-not-address:
    23934     (write-buffered *(ebp+0x10) "fn ")
    23935     8b/-> *(ebp+0xc) 0/r32/eax
    23936     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23937     (write-buffered *(ebp+0x10) %eax)
    23938     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
    23939     (flush *(ebp+0x10))
    23940     (stop *(ebp+0x14) 1)
    23941     # never gets here
    23942
    23943 $check-mu-get-stmt:error-bad-output-type:
    23944     (write-buffered *(ebp+0x10) "fn ")
    23945     8b/-> *(ebp+0xc) 0/r32/eax
    23946     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23947     (write-buffered *(ebp+0x10) %eax)
    23948     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
    23949     (write-buffered *(ebp+0x10) %ecx)
    23950     (write-buffered *(ebp+0x10) "' of type '")
    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     (write-buffered *(ebp+0x10) "'\n")
    23959     (flush *(ebp+0x10))
    23960     (stop *(ebp+0x14) 1)
    23961     # never gets here
    23962
    23963 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23964     # . prologue
    23965     55/push-ebp
    23966     89/<- %ebp 4/r32/esp
    23967     # . save registers
    23968     50/push-eax
    23969     51/push-ecx
    23970     52/push-edx
    23971     53/push-ebx
    23972     56/push-esi
    23973     57/push-edi
    23974     # esi = stmt
    23975     8b/-> *(ebp+8) 6/r32/esi
    23976     # - check for 0 inouts
    23977     # var base/ecx: (addr var) = stmt->inouts->value
    23978     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23979 $check-mu-index-stmt:check-no-inouts:
    23980     3d/compare-eax-and 0/imm32
    23981     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    23982     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23983     89/<- %ecx 0/r32/eax
    23984     # - check base type is either (addr array ...) in register or (array ...) on stack
    23985     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    23986     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    23987     89/<- %ebx 0/r32/eax
    23988     # if base-type is an atom, abort with a precise error
    23989     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23990     {
    23991       74/jump-if-= break/disp8
    23992       (simple-mu-type? %ebx 3)  # array => eax
    23993       3d/compare-eax-and 0/imm32/false
    23994       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
    23995       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    23996     }
    23997 $check-mu-index-stmt:base-is-compound:
    23998     # if type->left not addr or array, abort
    23999     {
    24000       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24001       (simple-mu-type? %eax 2)  # addr => eax
    24002       3d/compare-eax-and 0/imm32/false
    24003       75/jump-if-!= break/disp8
    24004       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24005       (simple-mu-type? %eax 3)  # array => eax
    24006       3d/compare-eax-and 0/imm32/false
    24007       75/jump-if-!= break/disp8
    24008       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
    24009     }
    24010     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24011     {
    24012       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24013       (simple-mu-type? %eax 2)  # addr => eax
    24014       3d/compare-eax-and 0/imm32/false
    24015       74/jump-if-= break/disp8
    24016 $check-mu-index-stmt:base-is-addr:
    24017       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24018       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24019       (simple-mu-type? %eax 3)  # array => eax
    24020       3d/compare-eax-and 0/imm32/false
    24021       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    24022 $check-mu-index-stmt:check-base-addr-is-register:
    24023       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24024       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
    24025     }
    24026     # if (type->left == array) ensure type->register doesn't exist
    24027     {
    24028       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24029       (simple-mu-type? %eax 3)  # array => eax
    24030       3d/compare-eax-and 0/imm32/false
    24031       74/jump-if-= break/disp8
    24032 $check-mu-index-stmt:base-is-array:
    24033       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24034       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
    24035     }
    24036     # if (base-type->left == addr) base-type = base-type->right
    24037     {
    24038       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24039       (simple-mu-type? %eax 2)  # addr => eax
    24040       3d/compare-eax-and 0/imm32/false
    24041       74/jump-if-= break/disp8
    24042       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24043       89/<- %ebx 0/r32/eax
    24044     }
    24045     # - check for 1 inout
    24046     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24047     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24048     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24049 $check-mu-index-stmt:check-single-inout:
    24050     3d/compare-eax-and 0/imm32
    24051     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    24052     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24053     89/<- %ecx 0/r32/eax
    24054     # - check index is either a literal or register
    24055     # var index-type/edx: (addr type-tree)
    24056     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24057     89/<- %edx 0/r32/eax
    24058     # if index type is an atom, it must be a literal or int
    24059     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24060     {
    24061       74/jump-if-= break/disp8
    24062 $check-mu-index-stmt:index-type-is-atom:
    24063       (simple-mu-type? %edx 0)  # literal => eax
    24064       3d/compare-eax-and 0/imm32/false
    24065       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24066       (simple-mu-type? %edx 1)  # int => eax
    24067       3d/compare-eax-and 0/imm32/false
    24068       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24069       (simple-mu-type? %edx 7)  # offset => eax
    24070       3d/compare-eax-and 0/imm32/false
    24071       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
    24072       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
    24073     }
    24074     # if index type is a non-atom: it must be an offset
    24075     {
    24076       75/jump-if-!= break/disp8
    24077 $check-mu-index-stmt:index-type-is-non-atom:
    24078       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24079       (simple-mu-type? %eax 7)  # offset => eax
    24080       3d/compare-eax-and 0/imm32/false
    24081       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
    24082     }
    24083 $check-mu-index-stmt:index-type-done:
    24084     # check index is either a literal or in a register
    24085     {
    24086       (simple-mu-type? %edx 0)  # literal => eax
    24087       3d/compare-eax-and 0/imm32/false
    24088       75/jump-if-!= break/disp8
    24089 $check-mu-index-stmt:check-index-in-register:
    24090       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24091       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
    24092     }
    24093     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
    24094     {
    24095       (simple-mu-type? %edx 1)  # int => eax
    24096       3d/compare-eax-and 0/imm32/false
    24097       74/jump-if-= break/disp8
    24098 $check-mu-index-stmt:check-index-can-be-int:
    24099       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24100       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24101       (array-element-size %eax)  # => eax
    24102       3d/compare-eax-and 1/imm32
    24103       74/jump-if-= break/disp8
    24104       3d/compare-eax-and 2/imm32
    24105       74/jump-if-= break/disp8
    24106       3d/compare-eax-and 4/imm32
    24107       74/jump-if-= break/disp8
    24108       3d/compare-eax-and 8/imm32
    24109       74/jump-if-= break/disp8
    24110       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
    24111     }
    24112     # - check for too many inouts
    24113     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24114     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24115     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24116     3d/compare-eax-and 0/imm32/false
    24117     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
    24118     # - check for 0 outputs
    24119     # var output/edi: (addr var) = stmt->outputs->value
    24120     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24121     3d/compare-eax-and 0/imm32/false
    24122     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
    24123     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24124     89/<- %edi 0/r32/eax
    24125     # - check output type
    24126     # must have a non-atomic type
    24127     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24128     89/<- %edx 0/r32/eax
    24129     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24130     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
    24131     # type must start with (addr ...)
    24132     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24133     (simple-mu-type? %eax 2)  # addr => eax
    24134     3d/compare-eax-and 0/imm32/false
    24135     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
    24136     # if tail(base-type) != tail(output-type) abort
    24137     (type-tail %ebx)  # => eax
    24138     89/<- %ebx 0/r32/eax
    24139     (type-tail %edx)  # => eax
    24140     (type-equal? %ebx %eax)  # => eax
    24141     3d/compare-eax-and 0/imm32/false
    24142     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
    24143     # - check for too many outputs
    24144     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24145     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24146     3d/compare-eax-and 0/imm32/false
    24147     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
    24148 $check-mu-index-stmt:end:
    24149     # . restore registers
    24150     5f/pop-to-edi
    24151     5e/pop-to-esi
    24152     5b/pop-to-ebx
    24153     5a/pop-to-edx
    24154     59/pop-to-ecx
    24155     58/pop-to-eax
    24156     # . epilogue
    24157     89/<- %esp 5/r32/ebp
    24158     5d/pop-to-ebp
    24159     c3/return
    24160
    24161 $check-mu-index-stmt:error-base-non-array-type:
    24162     (write-buffered *(ebp+0x10) "fn ")
    24163     8b/-> *(ebp+0xc) 0/r32/eax
    24164     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24165     (write-buffered *(ebp+0x10) %eax)
    24166     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24167     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24168     (write-buffered *(ebp+0x10) %eax)
    24169     (write-buffered *(ebp+0x10) "' is not an array\n")
    24170     (flush *(ebp+0x10))
    24171     (stop *(ebp+0x14) 1)
    24172     # never gets here
    24173
    24174 $check-mu-index-stmt:error-base-array-atom-type:
    24175     (write-buffered *(ebp+0x10) "fn ")
    24176     8b/-> *(ebp+0xc) 0/r32/eax
    24177     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24178     (write-buffered *(ebp+0x10) %eax)
    24179     (write-buffered *(ebp+0x10) ": stmt index: array '")
    24180     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24181     (write-buffered *(ebp+0x10) %eax)
    24182     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24183     (flush *(ebp+0x10))
    24184     (stop *(ebp+0x14) 1)
    24185     # never gets here
    24186
    24187 $check-mu-index-stmt:error-base-address-array-type-on-stack:
    24188     (write-buffered *(ebp+0x10) "fn ")
    24189     8b/-> *(ebp+0xc) 0/r32/eax
    24190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24191     (write-buffered *(ebp+0x10) %eax)
    24192     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24193     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24194     (write-buffered *(ebp+0x10) %eax)
    24195     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24196     (flush *(ebp+0x10))
    24197     (stop *(ebp+0x14) 1)
    24198     # never gets here
    24199
    24200 $check-mu-index-stmt:error-base-array-type-in-register:
    24201     (write-buffered *(ebp+0x10) "fn ")
    24202     8b/-> *(ebp+0xc) 0/r32/eax
    24203     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24204     (write-buffered *(ebp+0x10) %eax)
    24205     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24206     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24207     (write-buffered *(ebp+0x10) %eax)
    24208     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24209     (flush *(ebp+0x10))
    24210     (stop *(ebp+0x14) 1)
    24211     # never gets here
    24212
    24213 $check-mu-index-stmt:error-too-few-inouts:
    24214     (write-buffered *(ebp+0x10) "fn ")
    24215     8b/-> *(ebp+0xc) 0/r32/eax
    24216     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24217     (write-buffered *(ebp+0x10) %eax)
    24218     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
    24219     (flush *(ebp+0x10))
    24220     (stop *(ebp+0x14) 1)
    24221     # never gets here
    24222
    24223 $check-mu-index-stmt:error-invalid-index-type:
    24224     (write-buffered *(ebp+0x10) "fn ")
    24225     8b/-> *(ebp+0xc) 0/r32/eax
    24226     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24227     (write-buffered *(ebp+0x10) %eax)
    24228     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24229     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24230     (write-buffered *(ebp+0x10) %eax)
    24231     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24232     (flush *(ebp+0x10))
    24233     (stop *(ebp+0x14) 1)
    24234     # never gets here
    24235
    24236 $check-mu-index-stmt:error-index-offset-atom-type:
    24237     (write-buffered *(ebp+0x10) "fn ")
    24238     8b/-> *(ebp+0xc) 0/r32/eax
    24239     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24240     (write-buffered *(ebp+0x10) %eax)
    24241     (write-buffered *(ebp+0x10) ": stmt index: offset '")
    24242     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24243     (write-buffered *(ebp+0x10) %eax)
    24244     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24245     (flush *(ebp+0x10))
    24246     (stop *(ebp+0x14) 1)
    24247     # never gets here
    24248
    24249 $check-mu-index-stmt:error-index-on-stack:
    24250     (write-buffered *(ebp+0x10) "fn ")
    24251     8b/-> *(ebp+0xc) 0/r32/eax
    24252     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24253     (write-buffered *(ebp+0x10) %eax)
    24254     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24255     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24256     (write-buffered *(ebp+0x10) %eax)
    24257     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24258     (flush *(ebp+0x10))
    24259     (stop *(ebp+0x14) 1)
    24260     # never gets here
    24261
    24262 $check-mu-index-stmt:error-index-needs-offset:
    24263     (write-buffered *(ebp+0x10) "fn ")
    24264     8b/-> *(ebp+0xc) 0/r32/eax
    24265     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24266     (write-buffered *(ebp+0x10) %eax)
    24267     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
    24268     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24269     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24270     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24271     (write-buffered *(ebp+0x10) %eax)
    24272     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24273     (flush *(ebp+0x10))
    24274     (stop *(ebp+0x14) 1)
    24275     # never gets here
    24276
    24277 $check-mu-index-stmt:error-too-many-inouts:
    24278     (write-buffered *(ebp+0x10) "fn ")
    24279     8b/-> *(ebp+0xc) 0/r32/eax
    24280     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24281     (write-buffered *(ebp+0x10) %eax)
    24282     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
    24283     (flush *(ebp+0x10))
    24284     (stop *(ebp+0x14) 1)
    24285     # never gets here
    24286
    24287 $check-mu-index-stmt:error-too-few-outputs:
    24288     (write-buffered *(ebp+0x10) "fn ")
    24289     8b/-> *(ebp+0xc) 0/r32/eax
    24290     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24291     (write-buffered *(ebp+0x10) %eax)
    24292     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
    24293     (flush *(ebp+0x10))
    24294     (stop *(ebp+0x14) 1)
    24295     # never gets here
    24296
    24297 $check-mu-index-stmt:error-too-many-outputs:
    24298     (write-buffered *(ebp+0x10) "fn ")
    24299     8b/-> *(ebp+0xc) 0/r32/eax
    24300     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24301     (write-buffered *(ebp+0x10) %eax)
    24302     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
    24303     (flush *(ebp+0x10))
    24304     (stop *(ebp+0x14) 1)
    24305     # never gets here
    24306
    24307 $check-mu-index-stmt:error-output-not-in-register:
    24308     (write-buffered *(ebp+0x10) "fn ")
    24309     8b/-> *(ebp+0xc) 0/r32/eax
    24310     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24311     (write-buffered *(ebp+0x10) %eax)
    24312     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24313     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24314     (write-buffered *(ebp+0x10) %eax)
    24315     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24316     (flush *(ebp+0x10))
    24317     (stop *(ebp+0x14) 1)
    24318     # never gets here
    24319
    24320 $check-mu-index-stmt:error-output-type-not-address:
    24321     (write-buffered *(ebp+0x10) "fn ")
    24322     8b/-> *(ebp+0xc) 0/r32/eax
    24323     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24324     (write-buffered *(ebp+0x10) %eax)
    24325     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24326     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24327     (write-buffered *(ebp+0x10) %eax)
    24328     (write-buffered *(ebp+0x10) "' must be an addr\n")
    24329     (flush *(ebp+0x10))
    24330     (stop *(ebp+0x14) 1)
    24331     # never gets here
    24332
    24333 $check-mu-index-stmt:error-bad-output-type:
    24334     (write-buffered *(ebp+0x10) "fn ")
    24335     8b/-> *(ebp+0xc) 0/r32/eax
    24336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24337     (write-buffered *(ebp+0x10) %eax)
    24338     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24339     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24340     (write-buffered *(ebp+0x10) %eax)
    24341     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24342     (flush *(ebp+0x10))
    24343     (stop *(ebp+0x14) 1)
    24344     # never gets here
    24345
    24346 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24347     # . prologue
    24348     55/push-ebp
    24349     89/<- %ebp 4/r32/esp
    24350     # . save registers
    24351     50/push-eax
    24352     51/push-ecx
    24353     52/push-edx
    24354     53/push-ebx
    24355     56/push-esi
    24356     57/push-edi
    24357     # esi = stmt
    24358     8b/-> *(ebp+8) 6/r32/esi
    24359     # - check for 0 inouts
    24360     # var base/ecx: (addr var) = stmt->inouts->value
    24361     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24362 $check-mu-length-stmt:check-no-inouts:
    24363     3d/compare-eax-and 0/imm32
    24364     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
    24365     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24366     89/<- %ecx 0/r32/eax
    24367     # - check base type is either (addr array ...) in register or (array ...) on stack
    24368     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24369     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24370     89/<- %ebx 0/r32/eax
    24371     # if base-type is an atom, abort with a precise error
    24372     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24373     {
    24374       74/jump-if-= break/disp8
    24375       (simple-mu-type? %ebx 3)  # array => eax
    24376       3d/compare-eax-and 0/imm32/false
    24377       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
    24378       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24379     }
    24380 $check-mu-length-stmt:base-is-compound:
    24381     # if type->left not addr or array, abort
    24382     {
    24383       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24384       (simple-mu-type? %eax 2)  # addr => eax
    24385       3d/compare-eax-and 0/imm32/false
    24386       75/jump-if-!= break/disp8
    24387       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24388       (simple-mu-type? %eax 3)  # array => eax
    24389       3d/compare-eax-and 0/imm32/false
    24390       75/jump-if-!= break/disp8
    24391       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
    24392     }
    24393     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24394     {
    24395       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24396       (simple-mu-type? %eax 2)  # addr => eax
    24397       3d/compare-eax-and 0/imm32/false
    24398       74/jump-if-= break/disp8
    24399 $check-mu-length-stmt:base-is-addr:
    24400       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24401       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24402       (simple-mu-type? %eax 3)  # array => eax
    24403       3d/compare-eax-and 0/imm32/false
    24404       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24405 $check-mu-length-stmt:check-base-addr-is-register:
    24406       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24407       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
    24408     }
    24409     # if (type->left == array) ensure type->register doesn't exist
    24410     {
    24411       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24412       (simple-mu-type? %eax 3)  # array => eax
    24413       3d/compare-eax-and 0/imm32/false
    24414       74/jump-if-= break/disp8
    24415 $check-mu-length-stmt:base-is-array:
    24416       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24417       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
    24418     }
    24419     # if (base-type->left == addr) base-type = base-type->right
    24420     {
    24421       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24422       (simple-mu-type? %eax 2)  # addr => eax
    24423       3d/compare-eax-and 0/imm32/false
    24424       74/jump-if-= break/disp8
    24425       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24426       89/<- %ebx 0/r32/eax
    24427     }
    24428     # - check for too many inouts
    24429     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24430     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24431     3d/compare-eax-and 0/imm32/false
    24432     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
    24433     # - check for 0 outputs
    24434     # var output/edi: (addr var) = stmt->outputs->value
    24435     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24436     3d/compare-eax-and 0/imm32/false
    24437     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
    24438     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24439     89/<- %edi 0/r32/eax
    24440     # - check output type
    24441     # must have a non-atomic type
    24442     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24443     (simple-mu-type? %eax 1)  # int => eax
    24444     3d/compare-eax-and 0/imm32/false
    24445     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
    24446     # - check for too many outputs
    24447     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24448     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24449     3d/compare-eax-and 0/imm32/false
    24450     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
    24451 $check-mu-length-stmt:end:
    24452     # . restore registers
    24453     5f/pop-to-edi
    24454     5e/pop-to-esi
    24455     5b/pop-to-ebx
    24456     5a/pop-to-edx
    24457     59/pop-to-ecx
    24458     58/pop-to-eax
    24459     # . epilogue
    24460     89/<- %esp 5/r32/ebp
    24461     5d/pop-to-ebp
    24462     c3/return
    24463
    24464 $check-mu-length-stmt:error-base-non-array-type:
    24465     (write-buffered *(ebp+0x10) "fn ")
    24466     8b/-> *(ebp+0xc) 0/r32/eax
    24467     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24468     (write-buffered *(ebp+0x10) %eax)
    24469     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24470     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24471     (write-buffered *(ebp+0x10) %eax)
    24472     (write-buffered *(ebp+0x10) "' is not an array\n")
    24473     (flush *(ebp+0x10))
    24474     (stop *(ebp+0x14) 1)
    24475     # never gets here
    24476
    24477 $check-mu-length-stmt:error-base-array-atom-type:
    24478     (write-buffered *(ebp+0x10) "fn ")
    24479     8b/-> *(ebp+0xc) 0/r32/eax
    24480     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24481     (write-buffered *(ebp+0x10) %eax)
    24482     (write-buffered *(ebp+0x10) ": stmt length: array '")
    24483     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24484     (write-buffered *(ebp+0x10) %eax)
    24485     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24486     (flush *(ebp+0x10))
    24487     (stop *(ebp+0x14) 1)
    24488     # never gets here
    24489
    24490 $check-mu-length-stmt:error-base-address-array-type-on-stack:
    24491     (write-buffered *(ebp+0x10) "fn ")
    24492     8b/-> *(ebp+0xc) 0/r32/eax
    24493     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24494     (write-buffered *(ebp+0x10) %eax)
    24495     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24496     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24497     (write-buffered *(ebp+0x10) %eax)
    24498     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24499     (flush *(ebp+0x10))
    24500     (stop *(ebp+0x14) 1)
    24501     # never gets here
    24502
    24503 $check-mu-length-stmt:error-base-array-type-in-register:
    24504     (write-buffered *(ebp+0x10) "fn ")
    24505     8b/-> *(ebp+0xc) 0/r32/eax
    24506     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24507     (write-buffered *(ebp+0x10) %eax)
    24508     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24509     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24510     (write-buffered *(ebp+0x10) %eax)
    24511     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24512     (flush *(ebp+0x10))
    24513     (stop *(ebp+0x14) 1)
    24514     # never gets here
    24515
    24516 $check-mu-length-stmt:error-too-few-inouts:
    24517     (write-buffered *(ebp+0x10) "fn ")
    24518     8b/-> *(ebp+0xc) 0/r32/eax
    24519     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24520     (write-buffered *(ebp+0x10) %eax)
    24521     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
    24522     (flush *(ebp+0x10))
    24523     (stop *(ebp+0x14) 1)
    24524     # never gets here
    24525
    24526 $check-mu-length-stmt:error-invalid-index-type:
    24527     (write-buffered *(ebp+0x10) "fn ")
    24528     8b/-> *(ebp+0xc) 0/r32/eax
    24529     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24530     (write-buffered *(ebp+0x10) %eax)
    24531     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24532     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24533     (write-buffered *(ebp+0x10) %eax)
    24534     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24535     (flush *(ebp+0x10))
    24536     (stop *(ebp+0x14) 1)
    24537     # never gets here
    24538
    24539 $check-mu-length-stmt:error-index-offset-atom-type:
    24540     (write-buffered *(ebp+0x10) "fn ")
    24541     8b/-> *(ebp+0xc) 0/r32/eax
    24542     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24543     (write-buffered *(ebp+0x10) %eax)
    24544     (write-buffered *(ebp+0x10) ": stmt length: offset '")
    24545     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24546     (write-buffered *(ebp+0x10) %eax)
    24547     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24548     (flush *(ebp+0x10))
    24549     (stop *(ebp+0x14) 1)
    24550     # never gets here
    24551
    24552 $check-mu-length-stmt:error-index-on-stack:
    24553     (write-buffered *(ebp+0x10) "fn ")
    24554     8b/-> *(ebp+0xc) 0/r32/eax
    24555     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24556     (write-buffered *(ebp+0x10) %eax)
    24557     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24558     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24559     (write-buffered *(ebp+0x10) %eax)
    24560     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24561     (flush *(ebp+0x10))
    24562     (stop *(ebp+0x14) 1)
    24563     # never gets here
    24564
    24565 $check-mu-length-stmt:error-index-needs-offset:
    24566     (write-buffered *(ebp+0x10) "fn ")
    24567     8b/-> *(ebp+0xc) 0/r32/eax
    24568     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24569     (write-buffered *(ebp+0x10) %eax)
    24570     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
    24571     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24572     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24573     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24574     (write-buffered *(ebp+0x10) %eax)
    24575     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24576     (flush *(ebp+0x10))
    24577     (stop *(ebp+0x14) 1)
    24578     # never gets here
    24579
    24580 $check-mu-length-stmt:error-too-many-inouts:
    24581     (write-buffered *(ebp+0x10) "fn ")
    24582     8b/-> *(ebp+0xc) 0/r32/eax
    24583     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24584     (write-buffered *(ebp+0x10) %eax)
    24585     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
    24586     (flush *(ebp+0x10))
    24587     (stop *(ebp+0x14) 1)
    24588     # never gets here
    24589
    24590 $check-mu-length-stmt:error-too-few-outputs:
    24591     (write-buffered *(ebp+0x10) "fn ")
    24592     8b/-> *(ebp+0xc) 0/r32/eax
    24593     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24594     (write-buffered *(ebp+0x10) %eax)
    24595     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
    24596     (flush *(ebp+0x10))
    24597     (stop *(ebp+0x14) 1)
    24598     # never gets here
    24599
    24600 $check-mu-length-stmt:error-too-many-outputs:
    24601     (write-buffered *(ebp+0x10) "fn ")
    24602     8b/-> *(ebp+0xc) 0/r32/eax
    24603     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24604     (write-buffered *(ebp+0x10) %eax)
    24605     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
    24606     (flush *(ebp+0x10))
    24607     (stop *(ebp+0x14) 1)
    24608     # never gets here
    24609
    24610 $check-mu-length-stmt:error-output-not-in-register:
    24611     (write-buffered *(ebp+0x10) "fn ")
    24612     8b/-> *(ebp+0xc) 0/r32/eax
    24613     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24614     (write-buffered *(ebp+0x10) %eax)
    24615     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24616     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24617     (write-buffered *(ebp+0x10) %eax)
    24618     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24619     (flush *(ebp+0x10))
    24620     (stop *(ebp+0x14) 1)
    24621     # never gets here
    24622
    24623 $check-mu-length-stmt:error-invalid-output-type:
    24624     (write-buffered *(ebp+0x10) "fn ")
    24625     8b/-> *(ebp+0xc) 0/r32/eax
    24626     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24627     (write-buffered *(ebp+0x10) %eax)
    24628     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24629     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24630     (write-buffered *(ebp+0x10) %eax)
    24631     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24632     (flush *(ebp+0x10))
    24633     (stop *(ebp+0x14) 1)
    24634     # never gets here
    24635
    24636 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24637     # . prologue
    24638     55/push-ebp
    24639     89/<- %ebp 4/r32/esp
    24640     # . save registers
    24641     50/push-eax
    24642     51/push-ecx
    24643     52/push-edx
    24644     53/push-ebx
    24645     56/push-esi
    24646     57/push-edi
    24647     # esi = stmt
    24648     8b/-> *(ebp+8) 6/r32/esi
    24649     # - check for 0 inouts
    24650     # var base/ecx: (addr var) = stmt->inouts->value
    24651     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24652 $check-mu-compute-offset-stmt:check-no-inouts:
    24653     3d/compare-eax-and 0/imm32
    24654     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24655     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24656     89/<- %ecx 0/r32/eax
    24657     # - check base type is either (addr array ...) in register or (array ...) on stack
    24658     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24659     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24660     89/<- %ebx 0/r32/eax
    24661     # if base-type is an atom, abort with a precise error
    24662     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24663     {
    24664       74/jump-if-= break/disp8
    24665       (simple-mu-type? %ebx 3)  # array => eax
    24666       3d/compare-eax-and 0/imm32/false
    24667       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
    24668       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24669     }
    24670 $check-mu-compute-offset-stmt:base-is-compound:
    24671     # if type->left not addr or array, abort
    24672     {
    24673       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24674       (simple-mu-type? %eax 2)  # addr => eax
    24675       3d/compare-eax-and 0/imm32/false
    24676       75/jump-if-!= break/disp8
    24677       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24678       (simple-mu-type? %eax 3)  # array => eax
    24679       3d/compare-eax-and 0/imm32/false
    24680       75/jump-if-!= break/disp8
    24681       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24682     }
    24683     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24684     {
    24685       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24686       (simple-mu-type? %eax 2)  # addr => eax
    24687       3d/compare-eax-and 0/imm32/false
    24688       74/jump-if-= break/disp8
    24689 $check-mu-compute-offset-stmt:base-is-addr:
    24690       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24691       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24692       (simple-mu-type? %eax 3)  # array => eax
    24693       3d/compare-eax-and 0/imm32/false
    24694       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24695     }
    24696     # if (base-type->left == addr) base-type = base-type->right
    24697     {
    24698       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24699       (simple-mu-type? %eax 2)  # addr => eax
    24700       3d/compare-eax-and 0/imm32/false
    24701       74/jump-if-= break/disp8
    24702       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24703       89/<- %ebx 0/r32/eax
    24704     }
    24705     # - check for 1 inout
    24706     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24707     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24708     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24709 $check-mu-compute-offset-stmt:check-single-inout:
    24710     3d/compare-eax-and 0/imm32
    24711     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24712     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24713     89/<- %ecx 0/r32/eax
    24714     # - check index is either a literal or register
    24715     # var index-type/edx: (addr type-tree)
    24716     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24717     89/<- %edx 0/r32/eax
    24718     # index type must be a literal or int
    24719     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24720     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24721     {
    24722 $check-mu-compute-offset-stmt:index-type-is-atom:
    24723       (simple-mu-type? %edx 0)  # literal => eax
    24724       3d/compare-eax-and 0/imm32/false
    24725       75/jump-if-!= break/disp8
    24726       (simple-mu-type? %edx 1)  # int => eax
    24727       3d/compare-eax-and 0/imm32/false
    24728       75/jump-if-!= break/disp8
    24729       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24730     }
    24731     # - check for too many inouts
    24732     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24733     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24734     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24735     3d/compare-eax-and 0/imm32/false
    24736     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
    24737     # - check for 0 outputs
    24738     # var output/edi: (addr var) = stmt->outputs->value
    24739     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24740     3d/compare-eax-and 0/imm32/false
    24741     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
    24742     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24743     89/<- %edi 0/r32/eax
    24744     # - check output type
    24745     # must have a non-atomic type
    24746     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24747     89/<- %edx 0/r32/eax
    24748     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24749     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24750     # type must start with (offset ...)
    24751     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24752     (simple-mu-type? %eax 7)  # offset => eax
    24753     3d/compare-eax-and 0/imm32/false
    24754     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24755     # if tail(base-type) != tail(output-type) abort
    24756     (type-tail %ebx)  # => eax
    24757     89/<- %ebx 0/r32/eax
    24758     (type-tail %edx)  # => eax
    24759     (type-equal? %ebx %eax)  # => eax
    24760     3d/compare-eax-and 0/imm32/false
    24761     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
    24762     # - check for too many outputs
    24763     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24764     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24765     3d/compare-eax-and 0/imm32/false
    24766     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
    24767 $check-mu-compute-offset-stmt:end:
    24768     # . restore registers
    24769     5f/pop-to-edi
    24770     5e/pop-to-esi
    24771     5b/pop-to-ebx
    24772     5a/pop-to-edx
    24773     59/pop-to-ecx
    24774     58/pop-to-eax
    24775     # . epilogue
    24776     89/<- %esp 5/r32/ebp
    24777     5d/pop-to-ebp
    24778     c3/return
    24779
    24780 $check-mu-compute-offset-stmt:error-base-non-array-type:
    24781     (write-buffered *(ebp+0x10) "fn ")
    24782     8b/-> *(ebp+0xc) 0/r32/eax
    24783     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24784     (write-buffered *(ebp+0x10) %eax)
    24785     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
    24786     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24787     (write-buffered *(ebp+0x10) %eax)
    24788     (write-buffered *(ebp+0x10) "' is not an array\n")
    24789     (flush *(ebp+0x10))
    24790     (stop *(ebp+0x14) 1)
    24791     # never gets here
    24792
    24793 $check-mu-compute-offset-stmt:error-base-array-atom-type:
    24794     (write-buffered *(ebp+0x10) "fn ")
    24795     8b/-> *(ebp+0xc) 0/r32/eax
    24796     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24797     (write-buffered *(ebp+0x10) %eax)
    24798     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
    24799     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24800     (write-buffered *(ebp+0x10) %eax)
    24801     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24802     (flush *(ebp+0x10))
    24803     (stop *(ebp+0x14) 1)
    24804     # never gets here
    24805
    24806 $check-mu-compute-offset-stmt:error-too-few-inouts:
    24807     (write-buffered *(ebp+0x10) "fn ")
    24808     8b/-> *(ebp+0xc) 0/r32/eax
    24809     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24810     (write-buffered *(ebp+0x10) %eax)
    24811     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
    24812     (flush *(ebp+0x10))
    24813     (stop *(ebp+0x14) 1)
    24814     # never gets here
    24815
    24816 $check-mu-compute-offset-stmt:error-invalid-index-type:
    24817     (write-buffered *(ebp+0x10) "fn ")
    24818     8b/-> *(ebp+0xc) 0/r32/eax
    24819     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24820     (write-buffered *(ebp+0x10) %eax)
    24821     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24822     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24823     (write-buffered *(ebp+0x10) %eax)
    24824     (write-buffered *(ebp+0x10) "' must be an int\n")
    24825     (flush *(ebp+0x10))
    24826     (stop *(ebp+0x14) 1)
    24827     # never gets here
    24828
    24829 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
    24830     (write-buffered *(ebp+0x10) "fn ")
    24831     8b/-> *(ebp+0xc) 0/r32/eax
    24832     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24833     (write-buffered *(ebp+0x10) %eax)
    24834     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
    24835     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24836     (write-buffered *(ebp+0x10) %eax)
    24837     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24838     (flush *(ebp+0x10))
    24839     (stop *(ebp+0x14) 1)
    24840     # never gets here
    24841
    24842 $check-mu-compute-offset-stmt:error-index-on-stack:
    24843     (write-buffered *(ebp+0x10) "fn ")
    24844     8b/-> *(ebp+0xc) 0/r32/eax
    24845     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24846     (write-buffered *(ebp+0x10) %eax)
    24847     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24848     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24849     (write-buffered *(ebp+0x10) %eax)
    24850     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24851     (flush *(ebp+0x10))
    24852     (stop *(ebp+0x14) 1)
    24853     # never gets here
    24854
    24855 $check-mu-compute-offset-stmt:error-too-many-inouts:
    24856     (write-buffered *(ebp+0x10) "fn ")
    24857     8b/-> *(ebp+0xc) 0/r32/eax
    24858     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24859     (write-buffered *(ebp+0x10) %eax)
    24860     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
    24861     (flush *(ebp+0x10))
    24862     (stop *(ebp+0x14) 1)
    24863     # never gets here
    24864
    24865 $check-mu-compute-offset-stmt:error-too-few-outputs:
    24866     (write-buffered *(ebp+0x10) "fn ")
    24867     8b/-> *(ebp+0xc) 0/r32/eax
    24868     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24869     (write-buffered *(ebp+0x10) %eax)
    24870     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
    24871     (flush *(ebp+0x10))
    24872     (stop *(ebp+0x14) 1)
    24873     # never gets here
    24874
    24875 $check-mu-compute-offset-stmt:error-too-many-outputs:
    24876     (write-buffered *(ebp+0x10) "fn ")
    24877     8b/-> *(ebp+0xc) 0/r32/eax
    24878     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24879     (write-buffered *(ebp+0x10) %eax)
    24880     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
    24881     (flush *(ebp+0x10))
    24882     (stop *(ebp+0x14) 1)
    24883     # never gets here
    24884
    24885 $check-mu-compute-offset-stmt:error-output-not-in-register:
    24886     (write-buffered *(ebp+0x10) "fn ")
    24887     8b/-> *(ebp+0xc) 0/r32/eax
    24888     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24889     (write-buffered *(ebp+0x10) %eax)
    24890     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24891     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24892     (write-buffered *(ebp+0x10) %eax)
    24893     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24894     (flush *(ebp+0x10))
    24895     (stop *(ebp+0x14) 1)
    24896     # never gets here
    24897
    24898 $check-mu-compute-offset-stmt:error-output-type-not-offset:
    24899     (write-buffered *(ebp+0x10) "fn ")
    24900     8b/-> *(ebp+0xc) 0/r32/eax
    24901     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24902     (write-buffered *(ebp+0x10) %eax)
    24903     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24904     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24905     (write-buffered *(ebp+0x10) %eax)
    24906     (write-buffered *(ebp+0x10) "' must be an offset\n")
    24907     (flush *(ebp+0x10))
    24908     (stop *(ebp+0x14) 1)
    24909     # never gets here
    24910
    24911 $check-mu-compute-offset-stmt:error-bad-output-type:
    24912     (write-buffered *(ebp+0x10) "fn ")
    24913     8b/-> *(ebp+0xc) 0/r32/eax
    24914     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24915     (write-buffered *(ebp+0x10) %eax)
    24916     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24917     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24918     (write-buffered *(ebp+0x10) %eax)
    24919     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24920     (flush *(ebp+0x10))
    24921     (stop *(ebp+0x14) 1)
    24922     # never gets here
    24923
    24924 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24925     # . prologue
    24926     55/push-ebp
    24927     89/<- %ebp 4/r32/esp
    24928     # . save registers
    24929     50/push-eax
    24930     51/push-ecx
    24931     53/push-ebx
    24932     56/push-esi
    24933     57/push-edi
    24934     # esi = stmt
    24935     8b/-> *(ebp+8) 6/r32/esi
    24936 $check-mu-copy-object-stmt:check-for-output:
    24937     # if stmt->outputs abort
    24938     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24939     3d/compare-eax-and 0/imm32
    24940     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
    24941 $check-mu-copy-object-stmt:get-left:
    24942     # var dest/edi: (addr stmt-var) = stmt->inouts
    24943     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24944     89/<- %edi 0/r32/eax
    24945     # zero inouts
    24946     3d/compare-eax-and 0/imm32
    24947     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24948 $check-mu-copy-object-stmt:get-src:
    24949     # var src/esi: (addr stmt-var) = dest->next
    24950     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24951     89/<- %esi 0/r32/eax
    24952     # 1 inout
    24953     3d/compare-eax-and 0/imm32
    24954     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24955     # > 2 inouts
    24956     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24957     3d/compare-eax-and 0/imm32
    24958     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24959 $check-mu-copy-object-stmt:types:
    24960     # var src-type/ecx: (addr type-tree) = src->value->type
    24961     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    24962     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    24963     89/<- %ecx 0/r32/eax
    24964     # if (src->is-deref?) src-type = src-type->payload
    24965     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    24966     3d/compare-eax-and 0/imm32/false
    24967     {
    24968       74/jump-if-= break/disp8
    24969       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    24970       # if src-type->right is null, src-type = src-type->left
    24971       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    24972       {
    24973         75/jump-if-!= break/disp8
    24974         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24975       }
    24976       89/<- %ecx 0/r32/eax
    24977     }
    24978     # if src-type is not addr, abort
    24979     (mu-addr-type? %ecx)  # => eax
    24980     3d/compare-eax-and 0/imm32/false
    24981     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    24982     # var dest-type/ebx: (addr type-tree) = dest->value->type
    24983     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    24984     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    24985     89/<- %ebx 0/r32/eax
    24986     # if (dest->is-deref?) dest-type = dest-type->payload
    24987     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    24988     3d/compare-eax-and 0/imm32/false
    24989     {
    24990       74/jump-if-= break/disp8
    24991       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24992       # if dest-type->right is null, dest-type = dest-type->left
    24993       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    24994       {
    24995         75/jump-if-!= break/disp8
    24996         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24997       }
    24998       89/<- %ebx 0/r32/eax
    24999     }
    25000     # if (dest-type != src-type) abort
    25001     (type-equal? %ecx %ebx)  # => eax
    25002     3d/compare-eax-and 0/imm32
    25003     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    25004 $check-mu-copy-object-stmt:end:
    25005     # . restore registers
    25006     5f/pop-to-edi
    25007     5e/pop-to-esi
    25008     5b/pop-to-ebx
    25009     59/pop-to-ecx
    25010     58/pop-to-eax
    25011     # . epilogue
    25012     89/<- %esp 5/r32/ebp
    25013     5d/pop-to-ebp
    25014     c3/return
    25015
    25016 $check-mu-copy-object-stmt:error-incorrect-inouts:
    25017     (write-buffered *(ebp+0x10) "fn ")
    25018     8b/-> *(ebp+0xc) 0/r32/eax
    25019     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25020     (write-buffered *(ebp+0x10) %eax)
    25021     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
    25022     (flush *(ebp+0x10))
    25023     (stop *(ebp+0x14) 1)
    25024     # never gets here
    25025
    25026 $check-mu-copy-object-stmt:error-too-many-outputs:
    25027     (write-buffered *(ebp+0x10) "fn ")
    25028     8b/-> *(ebp+0xc) 0/r32/eax
    25029     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25030     (write-buffered *(ebp+0x10) %eax)
    25031     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
    25032     (flush *(ebp+0x10))
    25033     (stop *(ebp+0x14) 1)
    25034     # never gets here
    25035
    25036 $check-mu-copy-object-stmt:error-invalid-types:
    25037     (write-buffered *(ebp+0x10) "fn ")
    25038     8b/-> *(ebp+0xc) 0/r32/eax
    25039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25040     (write-buffered *(ebp+0x10) %eax)
    25041     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
    25042     (flush *(ebp+0x10))
    25043     (stop *(ebp+0x14) 1)
    25044     # never gets here
    25045
    25046 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25047     # . prologue
    25048     55/push-ebp
    25049     89/<- %ebp 4/r32/esp
    25050     # . save registers
    25051     50/push-eax
    25052     51/push-ecx
    25053     53/push-ebx
    25054     56/push-esi
    25055     57/push-edi
    25056     # esi = stmt
    25057     8b/-> *(ebp+8) 6/r32/esi
    25058 $check-mu-clear-object-stmt:check-for-output:
    25059     # if stmt->outputs abort
    25060     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25061     3d/compare-eax-and 0/imm32
    25062     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
    25063 $check-mu-clear-object-stmt:get-left:
    25064     # var dest/edi: (addr stmt-var) = stmt->inouts
    25065     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25066     89/<- %edi 0/r32/eax
    25067     # zero inouts
    25068     3d/compare-eax-and 0/imm32
    25069     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25070 $check-mu-clear-object-stmt:get-src:
    25071     # > 1 inout
    25072     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25073     3d/compare-eax-and 0/imm32
    25074     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25075 $check-mu-clear-object-stmt:types:
    25076     # var src-type/ecx: (addr type-tree) = src->value->type
    25077     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25078     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25079     89/<- %ecx 0/r32/eax
    25080     # if (src->is-deref?) src-type = src-type->payload
    25081     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25082     3d/compare-eax-and 0/imm32/false
    25083     {
    25084       74/jump-if-= break/disp8
    25085       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25086       # if src-type->right is null, src-type = src-type->left
    25087       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25088       {
    25089         75/jump-if-!= break/disp8
    25090         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25091       }
    25092       89/<- %ecx 0/r32/eax
    25093     }
    25094     # if src-type is not addr, abort
    25095     (mu-addr-type? %ecx)  # => eax
    25096     3d/compare-eax-and 0/imm32/false
    25097     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
    25098 $check-mu-clear-object-stmt:end:
    25099     # . restore registers
    25100     5f/pop-to-edi
    25101     5e/pop-to-esi
    25102     5b/pop-to-ebx
    25103     59/pop-to-ecx
    25104     58/pop-to-eax
    25105     # . epilogue
    25106     89/<- %esp 5/r32/ebp
    25107     5d/pop-to-ebp
    25108     c3/return
    25109
    25110 $check-mu-clear-object-stmt:error-incorrect-inouts:
    25111     (write-buffered *(ebp+0x10) "fn ")
    25112     8b/-> *(ebp+0xc) 0/r32/eax
    25113     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25114     (write-buffered *(ebp+0x10) %eax)
    25115     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
    25116     (flush *(ebp+0x10))
    25117     (stop *(ebp+0x14) 1)
    25118     # never gets here
    25119
    25120 $check-mu-clear-object-stmt:error-too-many-outputs:
    25121     (write-buffered *(ebp+0x10) "fn ")
    25122     8b/-> *(ebp+0xc) 0/r32/eax
    25123     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25124     (write-buffered *(ebp+0x10) %eax)
    25125     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
    25126     (flush *(ebp+0x10))
    25127     (stop *(ebp+0x14) 1)
    25128     # never gets here
    25129
    25130 $check-mu-clear-object-stmt:error-invalid-type:
    25131     (write-buffered *(ebp+0x10) "fn ")
    25132     8b/-> *(ebp+0xc) 0/r32/eax
    25133     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25134     (write-buffered *(ebp+0x10) %eax)
    25135     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
    25136     (flush *(ebp+0x10))
    25137     (stop *(ebp+0x14) 1)
    25138     # never gets here
    25139
    25140 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25141     # . prologue
    25142     55/push-ebp
    25143     89/<- %ebp 4/r32/esp
    25144     # . save registers
    25145     50/push-eax
    25146     53/push-ebx
    25147     56/push-esi
    25148     57/push-edi
    25149     # esi = stmt
    25150     8b/-> *(ebp+8) 6/r32/esi
    25151 $check-mu-allocate-stmt:check-for-output:
    25152     # if stmt->outputs abort
    25153     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25154     3d/compare-eax-and 0/imm32
    25155     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
    25156 $check-mu-allocate-stmt:get-target:
    25157     # var target/edi: (addr stmt-var) = stmt->inouts
    25158     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25159     89/<- %edi 0/r32/eax
    25160     # zero inouts
    25161     3d/compare-eax-and 0/imm32
    25162     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25163     # > 1 inouts
    25164     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25165     3d/compare-eax-and 0/imm32
    25166     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25167 $check-mu-allocate-stmt:check-type:
    25168     # var target-type/ebx: (addr type-tree) = target->value->type
    25169     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25170     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25171     89/<- %ebx 0/r32/eax
    25172     # if (target->is-deref?) target-type = target-type->payload
    25173     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25174     3d/compare-eax-and 0/imm32/false
    25175     {
    25176       74/jump-if-= break/disp8
    25177       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25178       # if target-type->right is null, target-type = target-type->left
    25179       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25180       {
    25181         75/jump-if-!= break/disp8
    25182         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25183       }
    25184       89/<- %ebx 0/r32/eax
    25185     }
    25186     # if target-type is not addr, abort
    25187     (mu-addr-type? %ebx)  # => eax
    25188     3d/compare-eax-and 0/imm32/false
    25189     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25190     # if target-type->right is an atom, abort
    25191     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25192     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    25193     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
    25194     # if target-type->right->left is not handle, abort
    25195     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25196     (simple-mu-type? %eax 4)  # handle => eax
    25197     3d/compare-eax-and 0/imm32/false
    25198     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25199 $check-mu-allocate-stmt:end:
    25200     # . restore registers
    25201     5f/pop-to-edi
    25202     5e/pop-to-esi
    25203     5b/pop-to-ebx
    25204     58/pop-to-eax
    25205     # . epilogue
    25206     89/<- %esp 5/r32/ebp
    25207     5d/pop-to-ebp
    25208     c3/return
    25209
    25210 $check-mu-allocate-stmt:error-incorrect-inouts:
    25211     (write-buffered *(ebp+0x10) "fn ")
    25212     8b/-> *(ebp+0xc) 0/r32/eax
    25213     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25214     (write-buffered *(ebp+0x10) %eax)
    25215     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
    25216     (flush *(ebp+0x10))
    25217     (stop *(ebp+0x14) 1)
    25218     # never gets here
    25219
    25220 $check-mu-allocate-stmt:error-too-many-outputs:
    25221     (write-buffered *(ebp+0x10) "fn ")
    25222     8b/-> *(ebp+0xc) 0/r32/eax
    25223     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25224     (write-buffered *(ebp+0x10) %eax)
    25225     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
    25226     (flush *(ebp+0x10))
    25227     (stop *(ebp+0x14) 1)
    25228     # never gets here
    25229
    25230 $check-mu-allocate-stmt:error-invalid-type:
    25231     (write-buffered *(ebp+0x10) "fn ")
    25232     8b/-> *(ebp+0xc) 0/r32/eax
    25233     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25234     (write-buffered *(ebp+0x10) %eax)
    25235     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
    25236     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25237     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25238     (write-buffered *(ebp+0x10) %eax)
    25239     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
    25240     (flush *(ebp+0x10))
    25241     (stop *(ebp+0x14) 1)
    25242     # never gets here
    25243
    25244 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25245     # . prologue
    25246     55/push-ebp
    25247     89/<- %ebp 4/r32/esp
    25248     # . save registers
    25249     50/push-eax
    25250     53/push-ebx
    25251     56/push-esi
    25252     57/push-edi
    25253     # esi = stmt
    25254     8b/-> *(ebp+8) 6/r32/esi
    25255 $check-mu-populate-stmt:check-for-output:
    25256     # if stmt->outputs abort
    25257     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25258     3d/compare-eax-and 0/imm32
    25259     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
    25260 $check-mu-populate-stmt:get-target:
    25261     # var target/edi: (addr stmt-var) = stmt->inouts
    25262     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25263     89/<- %edi 0/r32/eax
    25264     # zero inouts
    25265     3d/compare-eax-and 0/imm32
    25266     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25267 $check-mu-populate-stmt:get-length:
    25268     # var length/esi: (addr stmt-var) = dest->next
    25269     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25270     89/<- %esi 0/r32/eax
    25271     # 1 inout
    25272     3d/compare-eax-and 0/imm32
    25273     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25274     # > 2 inouts
    25275     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25276     3d/compare-eax-and 0/imm32
    25277     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25278 $check-mu-populate-stmt:check-target-type:
    25279     # var target-type/ebx: (addr type-tree) = target->value->type
    25280     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25281     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25282     89/<- %ebx 0/r32/eax
    25283 $check-mu-populate-stmt:check-target-type-deref:
    25284     # if (target->is-deref?) target-type = target-type->payload
    25285     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25286     3d/compare-eax-and 0/imm32/false
    25287     {
    25288       74/jump-if-= break/disp8
    25289       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25290       # if target-type->right is null, target-type = target-type->left
    25291       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25292       {
    25293         75/jump-if-!= break/disp8
    25294         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25295       }
    25296       89/<- %ebx 0/r32/eax
    25297     }
    25298 $check-mu-populate-stmt:check-target-type-addr:
    25299     # if target-type is not addr, abort
    25300     (mu-addr-type? %ebx)  # => eax
    25301     3d/compare-eax-and 0/imm32/false
    25302     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25303     # if target-type->right is an atom, abort
    25304     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25305     89/<- %ebx 0/r32/eax
    25306     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25307     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25308 $check-mu-populate-stmt:check-target-type-handle:
    25309     # if target-type->right->left is not handle, abort
    25310     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25311     (simple-mu-type? %eax 4)  # handle => eax
    25312     3d/compare-eax-and 0/imm32/false
    25313     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25314     # if target-type->right->right is an atom, abort
    25315     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25316     89/<- %ebx 0/r32/eax
    25317     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25318     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25319 $check-mu-populate-stmt:check-target-type-array:
    25320     # if target-type->right->right->left is not array, abort
    25321     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25322     (simple-mu-type? %eax 3)  # array => eax
    25323     3d/compare-eax-and 0/imm32/false
    25324     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25325 $check-mu-populate-stmt:check-length-type:
    25326     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25327     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25328     89/<- %ebx 0/r32/eax
    25329     (simple-mu-type? %ebx 0)  # literal => eax
    25330     3d/compare-eax-and 0/imm32/false
    25331     75/jump-if-!= $check-mu-populate-stmt:end/disp8
    25332     (simple-mu-type? %ebx 1)  # int => eax
    25333     3d/compare-eax-and 0/imm32/false
    25334     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
    25335 $check-mu-populate-stmt:end:
    25336     # . restore registers
    25337     5f/pop-to-edi
    25338     5e/pop-to-esi
    25339     5b/pop-to-ebx
    25340     58/pop-to-eax
    25341     # . epilogue
    25342     89/<- %esp 5/r32/ebp
    25343     5d/pop-to-ebp
    25344     c3/return
    25345
    25346 $check-mu-populate-stmt:error-incorrect-inouts:
    25347     (write-buffered *(ebp+0x10) "fn ")
    25348     8b/-> *(ebp+0xc) 0/r32/eax
    25349     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25350     (write-buffered *(ebp+0x10) %eax)
    25351     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
    25352     (flush *(ebp+0x10))
    25353     (stop *(ebp+0x14) 1)
    25354     # never gets here
    25355
    25356 $check-mu-populate-stmt:error-too-many-outputs:
    25357     (write-buffered *(ebp+0x10) "fn ")
    25358     8b/-> *(ebp+0xc) 0/r32/eax
    25359     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25360     (write-buffered *(ebp+0x10) %eax)
    25361     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
    25362     (flush *(ebp+0x10))
    25363     (stop *(ebp+0x14) 1)
    25364     # never gets here
    25365
    25366 $check-mu-populate-stmt:error-invalid-target-type:
    25367     (write-buffered *(ebp+0x10) "fn ")
    25368     8b/-> *(ebp+0xc) 0/r32/eax
    25369     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25370     (write-buffered *(ebp+0x10) %eax)
    25371     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
    25372     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25373     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25374     (write-buffered *(ebp+0x10) %eax)
    25375     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
    25376     (flush *(ebp+0x10))
    25377     (stop *(ebp+0x14) 1)
    25378     # never gets here
    25379
    25380 $check-mu-populate-stmt:error-invalid-length-type:
    25381     (write-buffered *(ebp+0x10) "fn ")
    25382     8b/-> *(ebp+0xc) 0/r32/eax
    25383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25384     (write-buffered *(ebp+0x10) %eax)
    25385     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
    25386     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25387     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25388     (write-buffered *(ebp+0x10) %eax)
    25389     (write-buffered *(ebp+0x10) "' must be an int\n")
    25390     (flush *(ebp+0x10))
    25391     (stop *(ebp+0x14) 1)
    25392     # never gets here
    25393
    25394 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25395     # . prologue
    25396     55/push-ebp
    25397     89/<- %ebp 4/r32/esp
    25398     # . save registers
    25399     50/push-eax
    25400     53/push-ebx
    25401     56/push-esi
    25402     57/push-edi
    25403     # esi = stmt
    25404     8b/-> *(ebp+8) 6/r32/esi
    25405 $check-mu-populate-stream-stmt:check-for-output:
    25406     # if stmt->outputs abort
    25407     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25408     3d/compare-eax-and 0/imm32
    25409     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
    25410 $check-mu-populate-stream-stmt:get-target:
    25411     # var target/edi: (addr stmt-var) = stmt->inouts
    25412     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25413     89/<- %edi 0/r32/eax
    25414     # zero inouts
    25415     3d/compare-eax-and 0/imm32
    25416     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25417 $check-mu-populate-stream-stmt:get-length:
    25418     # var length/esi: (addr stmt-var) = dest->next
    25419     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25420     89/<- %esi 0/r32/eax
    25421     # 1 inout
    25422     3d/compare-eax-and 0/imm32
    25423     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25424     # > 2 inouts
    25425     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25426     3d/compare-eax-and 0/imm32
    25427     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25428 $check-mu-populate-stream-stmt:check-target-type:
    25429     # var target-type/ebx: (addr type-tree) = target->value->type
    25430     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25431     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25432     89/<- %ebx 0/r32/eax
    25433 $check-mu-populate-stream-stmt:check-target-type-deref:
    25434     # if (target->is-deref?) target-type = target-type->payload
    25435     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25436     3d/compare-eax-and 0/imm32/false
    25437     {
    25438       74/jump-if-= break/disp8
    25439       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25440       # if target-type->right is null, target-type = target-type->left
    25441       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25442       {
    25443         75/jump-if-!= break/disp8
    25444         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25445       }
    25446       89/<- %ebx 0/r32/eax
    25447     }
    25448 $check-mu-populate-stream-stmt:check-target-type-addr:
    25449     # if target-type is not addr, abort
    25450     (mu-addr-type? %ebx)  # => eax
    25451     3d/compare-eax-and 0/imm32/false
    25452     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25453     # if target-type->right is an atom, abort
    25454     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25455     89/<- %ebx 0/r32/eax
    25456     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25457     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25458 $check-mu-populate-stream-stmt:check-target-type-handle:
    25459     # if target-type->right->left is not handle, abort
    25460     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25461     (simple-mu-type? %eax 4)  # handle => eax
    25462     3d/compare-eax-and 0/imm32/false
    25463     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25464     # if target-type->right->right is an atom, abort
    25465     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25466     89/<- %ebx 0/r32/eax
    25467     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25468     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25469 $check-mu-populate-stream-stmt:check-target-type-stream:
    25470     # if target-type->right->right->left is not stream, abort
    25471     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25472     (simple-mu-type? %eax 0xb)  # stream => eax
    25473     3d/compare-eax-and 0/imm32/false
    25474     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25475 $check-mu-populate-stream-stmt:check-length-type:
    25476     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25477     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25478     89/<- %ebx 0/r32/eax
    25479     (simple-mu-type? %ebx 0)  # literal => eax
    25480     3d/compare-eax-and 0/imm32/false
    25481     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
    25482     (simple-mu-type? %ebx 1)  # int => eax
    25483     3d/compare-eax-and 0/imm32/false
    25484     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
    25485 $check-mu-populate-stream-stmt:end:
    25486     # . restore registers
    25487     5f/pop-to-edi
    25488     5e/pop-to-esi
    25489     5b/pop-to-ebx
    25490     58/pop-to-eax
    25491     # . epilogue
    25492     89/<- %esp 5/r32/ebp
    25493     5d/pop-to-ebp
    25494     c3/return
    25495
    25496 $check-mu-populate-stream-stmt:error-incorrect-inouts:
    25497     (write-buffered *(ebp+0x10) "fn ")
    25498     8b/-> *(ebp+0xc) 0/r32/eax
    25499     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25500     (write-buffered *(ebp+0x10) %eax)
    25501     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
    25502     (flush *(ebp+0x10))
    25503     (stop *(ebp+0x14) 1)
    25504     # never gets here
    25505
    25506 $check-mu-populate-stream-stmt:error-too-many-outputs:
    25507     (write-buffered *(ebp+0x10) "fn ")
    25508     8b/-> *(ebp+0xc) 0/r32/eax
    25509     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25510     (write-buffered *(ebp+0x10) %eax)
    25511     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
    25512     (flush *(ebp+0x10))
    25513     (stop *(ebp+0x14) 1)
    25514     # never gets here
    25515
    25516 $check-mu-populate-stream-stmt:error-invalid-target-type:
    25517     (write-buffered *(ebp+0x10) "fn ")
    25518     8b/-> *(ebp+0xc) 0/r32/eax
    25519     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25520     (write-buffered *(ebp+0x10) %eax)
    25521     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
    25522     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25523     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25524     (write-buffered *(ebp+0x10) %eax)
    25525     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
    25526     (flush *(ebp+0x10))
    25527     (stop *(ebp+0x14) 1)
    25528     # never gets here
    25529
    25530 $check-mu-populate-stream-stmt:error-invalid-length-type:
    25531     (write-buffered *(ebp+0x10) "fn ")
    25532     8b/-> *(ebp+0xc) 0/r32/eax
    25533     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25534     (write-buffered *(ebp+0x10) %eax)
    25535     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
    25536     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25537     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25538     (write-buffered *(ebp+0x10) %eax)
    25539     (write-buffered *(ebp+0x10) "' must be an int\n")
    25540     (flush *(ebp+0x10))
    25541     (stop *(ebp+0x14) 1)
    25542     # never gets here
    25543
    25544 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25545     # . prologue
    25546     55/push-ebp
    25547     89/<- %ebp 4/r32/esp
    25548     # . save registers
    25549     50/push-eax
    25550     51/push-ecx
    25551     52/push-edx
    25552     53/push-ebx
    25553     56/push-esi
    25554     57/push-edi
    25555     # esi = stmt
    25556     8b/-> *(ebp+8) 6/r32/esi
    25557     # - check for 0 inouts
    25558     # var base/ecx: (addr var) = stmt->inouts->value
    25559     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25560 $check-mu-read-from-stream-stmt:check-no-inouts:
    25561     3d/compare-eax-and 0/imm32
    25562     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25563     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25564     89/<- %ecx 0/r32/eax
    25565     # - check base type is (addr stream T)
    25566     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25567     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25568     89/<- %ebx 0/r32/eax
    25569 $check-mu-read-from-stream-stmt:check-base-is-compound:
    25570     # if base-type is an atom, abort
    25571     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25572     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25573 $check-mu-read-from-stream-stmt:check-base-is-addr:
    25574     # if type->left not addr, abort
    25575     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25576     (simple-mu-type? %eax 2)  # addr => eax
    25577     3d/compare-eax-and 0/imm32/false
    25578     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25579 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
    25580     # base-type = base-type->right
    25581     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25582     89/<- %ebx 0/r32/eax
    25583     # ensure base-type->left == stream
    25584     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25585     (simple-mu-type? %eax 0xb)  # stream => eax
    25586     3d/compare-eax-and 0/imm32/false
    25587     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25588     # - check target type is (addr T)
    25589     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25590     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25591     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25592 $check-mu-read-from-stream-stmt:check-single-inout:
    25593     3d/compare-eax-and 0/imm32
    25594     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25595     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25596     89/<- %ecx 0/r32/eax
    25597     # var target-type/edx: (addr type-tree)
    25598     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25599     89/<- %edx 0/r32/eax
    25600     # if target-type is an atom, it must be a literal or int
    25601 $check-mu-read-from-stream-stmt:check-target-is-compound:
    25602     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25603     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25604 $check-mu-read-from-stream-stmt:check-target-type:
    25605     # target type must start with (addr ...)
    25606     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25607     (simple-mu-type? %eax 2)  # addr => eax
    25608     3d/compare-eax-and 0/imm32/false
    25609     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25610     # if tail(base-type) != tail(target-type) abort
    25611     (type-tail %ebx)  # => eax
    25612     89/<- %ebx 0/r32/eax
    25613     (type-tail %edx)  # => eax
    25614     (type-equal? %ebx %eax)  # => eax
    25615     3d/compare-eax-and 0/imm32/false
    25616     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
    25617 $check-mu-read-from-stream-stmt:check-too-many-inouts:
    25618     # - check for too many inouts
    25619     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25620     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25621     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25622     3d/compare-eax-and 0/imm32/false
    25623     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
    25624 $check-mu-read-from-stream-stmt:check-unexpected-output:
    25625     # - check for any output
    25626     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25627     3d/compare-eax-and 0/imm32/false
    25628     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
    25629 $check-mu-read-from-stream-stmt:end:
    25630     # . restore registers
    25631     5f/pop-to-edi
    25632     5e/pop-to-esi
    25633     5b/pop-to-ebx
    25634     5a/pop-to-edx
    25635     59/pop-to-ecx
    25636     58/pop-to-eax
    25637     # . epilogue
    25638     89/<- %esp 5/r32/ebp
    25639     5d/pop-to-ebp
    25640     c3/return
    25641
    25642 $check-mu-read-from-stream-stmt:error-invalid-base-type:
    25643     (write-buffered *(ebp+0x10) "fn ")
    25644     8b/-> *(ebp+0xc) 0/r32/eax
    25645     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25646     (write-buffered *(ebp+0x10) %eax)
    25647     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
    25648     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25649     (write-buffered *(ebp+0x10) %eax)
    25650     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
    25651     (flush *(ebp+0x10))
    25652     (stop *(ebp+0x14) 1)
    25653     # never gets here
    25654
    25655 $check-mu-read-from-stream-stmt:error-too-few-inouts:
    25656     (write-buffered *(ebp+0x10) "fn ")
    25657     8b/-> *(ebp+0xc) 0/r32/eax
    25658     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25659     (write-buffered *(ebp+0x10) %eax)
    25660     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
    25661     (flush *(ebp+0x10))
    25662     (stop *(ebp+0x14) 1)
    25663     # never gets here
    25664
    25665 $check-mu-read-from-stream-stmt:error-target-type-not-address:
    25666     (write-buffered *(ebp+0x10) "fn ")
    25667     8b/-> *(ebp+0xc) 0/r32/eax
    25668     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25669     (write-buffered *(ebp+0x10) %eax)
    25670     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
    25671     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25672     (write-buffered *(ebp+0x10) %eax)
    25673     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25674     (flush *(ebp+0x10))
    25675     (stop *(ebp+0x14) 1)
    25676     # never gets here
    25677
    25678 $check-mu-read-from-stream-stmt:error-invalid-target-type:
    25679     (write-buffered *(ebp+0x10) "fn ")
    25680     8b/-> *(ebp+0xc) 0/r32/eax
    25681     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25682     (write-buffered *(ebp+0x10) %eax)
    25683     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
    25684     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25685     (write-buffered *(ebp+0x10) %eax)
    25686     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25687     (flush *(ebp+0x10))
    25688     (stop *(ebp+0x14) 1)
    25689     # never gets here
    25690
    25691 $check-mu-read-from-stream-stmt:error-too-many-inouts:
    25692     (write-buffered *(ebp+0x10) "fn ")
    25693     8b/-> *(ebp+0xc) 0/r32/eax
    25694     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25695     (write-buffered *(ebp+0x10) %eax)
    25696     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
    25697     (flush *(ebp+0x10))
    25698     (stop *(ebp+0x14) 1)
    25699     # never gets here
    25700
    25701 $check-mu-read-from-stream-stmt:error-unexpected-output:
    25702     (write-buffered *(ebp+0x10) "fn ")
    25703     8b/-> *(ebp+0xc) 0/r32/eax
    25704     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25705     (write-buffered *(ebp+0x10) %eax)
    25706     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
    25707     (flush *(ebp+0x10))
    25708     (stop *(ebp+0x14) 1)
    25709     # never gets here
    25710
    25711 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25712     # . prologue
    25713     55/push-ebp
    25714     89/<- %ebp 4/r32/esp
    25715     # . save registers
    25716     50/push-eax
    25717     51/push-ecx
    25718     52/push-edx
    25719     53/push-ebx
    25720     56/push-esi
    25721     57/push-edi
    25722     # esi = stmt
    25723     8b/-> *(ebp+8) 6/r32/esi
    25724     # - check for 0 inouts
    25725     # var base/ecx: (addr var) = stmt->inouts->value
    25726     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25727 $check-mu-write-to-stream-stmt:check-no-inouts:
    25728     3d/compare-eax-and 0/imm32
    25729     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25730     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25731     89/<- %ecx 0/r32/eax
    25732     # - check base type is (addr stream T)
    25733     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25734     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25735     89/<- %ebx 0/r32/eax
    25736 $check-mu-write-to-stream-stmt:check-base-is-compound:
    25737     # if base-type is an atom, abort
    25738     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25739     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25740 $check-mu-write-to-stream-stmt:check-base-is-addr:
    25741     # if type->left not addr, abort
    25742     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25743     (simple-mu-type? %eax 2)  # addr => eax
    25744     3d/compare-eax-and 0/imm32/false
    25745     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25746 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
    25747     # base-type = base-type->right
    25748     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25749     89/<- %ebx 0/r32/eax
    25750     # ensure base-type->left == stream
    25751     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25752     (simple-mu-type? %eax 0xb)  # stream => eax
    25753     3d/compare-eax-and 0/imm32/false
    25754     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25755     # - check target type is (addr T)
    25756     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25757     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25758     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25759 $check-mu-write-to-stream-stmt:check-single-inout:
    25760     3d/compare-eax-and 0/imm32
    25761     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25762     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25763     89/<- %ecx 0/r32/eax
    25764     # var target-type/edx: (addr type-tree)
    25765     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25766     89/<- %edx 0/r32/eax
    25767     # if target-type is an atom, it must be a literal or int
    25768 $check-mu-write-to-stream-stmt:check-target-is-compound:
    25769     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25770     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25771 $check-mu-write-to-stream-stmt:check-target-type:
    25772     # target type must start with (addr ...)
    25773     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25774     (simple-mu-type? %eax 2)  # addr => eax
    25775     3d/compare-eax-and 0/imm32/false
    25776     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25777     # if tail(base-type) != tail(target-type) abort
    25778     (type-tail %ebx)  # => eax
    25779     89/<- %ebx 0/r32/eax
    25780     (type-tail %edx)  # => eax
    25781     (type-equal? %ebx %eax)  # => eax
    25782     3d/compare-eax-and 0/imm32/false
    25783     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
    25784 $check-mu-write-to-stream-stmt:check-too-many-inouts:
    25785     # - check for too many inouts
    25786     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25787     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25788     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25789     3d/compare-eax-and 0/imm32/false
    25790     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
    25791 $check-mu-write-to-stream-stmt:check-unexpected-output:
    25792     # - check for any output
    25793     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25794     3d/compare-eax-and 0/imm32/false
    25795     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
    25796 $check-mu-write-to-stream-stmt:end:
    25797     # . restore registers
    25798     5f/pop-to-edi
    25799     5e/pop-to-esi
    25800     5b/pop-to-ebx
    25801     5a/pop-to-edx
    25802     59/pop-to-ecx
    25803     58/pop-to-eax
    25804     # . epilogue
    25805     89/<- %esp 5/r32/ebp
    25806     5d/pop-to-ebp
    25807     c3/return
    25808
    25809 $check-mu-write-to-stream-stmt:error-invalid-base-type:
    25810     (write-buffered *(ebp+0x10) "fn ")
    25811     8b/-> *(ebp+0xc) 0/r32/eax
    25812     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25813     (write-buffered *(ebp+0x10) %eax)
    25814     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
    25815     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25816     (write-buffered *(ebp+0x10) %eax)
    25817     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
    25818     (flush *(ebp+0x10))
    25819     (stop *(ebp+0x14) 1)
    25820     # never gets here
    25821
    25822 $check-mu-write-to-stream-stmt:error-too-few-inouts:
    25823     (write-buffered *(ebp+0x10) "fn ")
    25824     8b/-> *(ebp+0xc) 0/r32/eax
    25825     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25826     (write-buffered *(ebp+0x10) %eax)
    25827     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
    25828     (flush *(ebp+0x10))
    25829     (stop *(ebp+0x14) 1)
    25830     # never gets here
    25831
    25832 $check-mu-write-to-stream-stmt:error-target-type-not-address:
    25833     (write-buffered *(ebp+0x10) "fn ")
    25834     8b/-> *(ebp+0xc) 0/r32/eax
    25835     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25836     (write-buffered *(ebp+0x10) %eax)
    25837     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
    25838     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25839     (write-buffered *(ebp+0x10) %eax)
    25840     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25841     (flush *(ebp+0x10))
    25842     (stop *(ebp+0x14) 1)
    25843     # never gets here
    25844
    25845 $check-mu-write-to-stream-stmt:error-invalid-target-type:
    25846     (write-buffered *(ebp+0x10) "fn ")
    25847     8b/-> *(ebp+0xc) 0/r32/eax
    25848     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25849     (write-buffered *(ebp+0x10) %eax)
    25850     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
    25851     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25852     (write-buffered *(ebp+0x10) %eax)
    25853     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25854     (flush *(ebp+0x10))
    25855     (stop *(ebp+0x14) 1)
    25856     # never gets here
    25857
    25858 $check-mu-write-to-stream-stmt:error-too-many-inouts:
    25859     (write-buffered *(ebp+0x10) "fn ")
    25860     8b/-> *(ebp+0xc) 0/r32/eax
    25861     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25862     (write-buffered *(ebp+0x10) %eax)
    25863     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
    25864     (flush *(ebp+0x10))
    25865     (stop *(ebp+0x14) 1)
    25866     # never gets here
    25867
    25868 $check-mu-write-to-stream-stmt:error-unexpected-output:
    25869     (write-buffered *(ebp+0x10) "fn ")
    25870     8b/-> *(ebp+0xc) 0/r32/eax
    25871     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25872     (write-buffered *(ebp+0x10) %eax)
    25873     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
    25874     (flush *(ebp+0x10))
    25875     (stop *(ebp+0x14) 1)
    25876     # never gets here
    25877
    25878 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25879     # . prologue
    25880     55/push-ebp
    25881     89/<- %ebp 4/r32/esp
    25882     # . save registers
    25883     50/push-eax
    25884     51/push-ecx
    25885     52/push-edx
    25886     56/push-esi
    25887     57/push-edi
    25888 $check-mu-convert-stmt:get-output:
    25889     # esi = stmt
    25890     8b/-> *(ebp+8) 6/r32/esi
    25891     # var output/edi: (addr stmt-var) = stmt->outputs
    25892     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25893     89/<- %edi 0/r32/eax
    25894     # zero outputs
    25895     3d/compare-eax-and 0/imm32
    25896     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
    25897     # > 1 output
    25898     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25899     3d/compare-eax-and 0/imm32
    25900     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
    25901 $check-mu-convert-stmt:get-inout:
    25902     # var inout/esi: (addr stmt-var) = stmt->inouts
    25903     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25904     89/<- %esi 0/r32/eax
    25905     # zero inouts
    25906     3d/compare-eax-and 0/imm32
    25907     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
    25908     # > 1 inout
    25909     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25910     3d/compare-eax-and 0/imm32
    25911     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
    25912 $check-mu-convert-stmt:types:
    25913     # var inout-type/ecx: (addr type-tree) = inout->value->type
    25914     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25915     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25916     89/<- %ecx 0/r32/eax
    25917     # if (inout->is-deref?) inout-type = inout-type->payload
    25918     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25919     3d/compare-eax-and 0/imm32/false
    25920     {
    25921       74/jump-if-= break/disp8
    25922       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25923       # if inout-type->right is null, t = inout-type->left
    25924       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25925       {
    25926         75/jump-if-!= break/disp8
    25927         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25928       }
    25929       89/<- %ecx 0/r32/eax
    25930     }
    25931     # if input is not int or float, abort
    25932     {
    25933       (simple-mu-type? %ecx 1)  # int => eax
    25934       3d/compare-eax-and 0/imm32/false
    25935       75/jump-if-!= break/disp8
    25936       (simple-mu-type? %ecx 0xf)  # float => eax
    25937       3d/compare-eax-and 0/imm32/false
    25938       75/jump-if-!= break/disp8
    25939       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
    25940     }
    25941     # if output not in register, abort
    25942     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25943     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    25944     3d/compare-eax-and 0/imm32
    25945     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
    25946     # var output-type/edx: (addr type-tree) = output->value->type
    25947     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25948     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25949     89/<- %edx 0/r32/eax
    25950     # if output is not int or float, abort
    25951     {
    25952       (simple-mu-type? %edx 1)  # int => eax
    25953       3d/compare-eax-and 0/imm32/false
    25954       75/jump-if-!= break/disp8
    25955       (simple-mu-type? %edx 0xf)  # float => eax
    25956       3d/compare-eax-and 0/imm32/false
    25957       75/jump-if-!= break/disp8
    25958       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
    25959     }
    25960     # if both are ints, abort
    25961     {
    25962       (simple-mu-type? %edx 1)  # int => eax
    25963       3d/compare-eax-and 0/imm32/false
    25964       74/jump-if-= break/disp8
    25965       (simple-mu-type? %ecx 1)  # int => eax
    25966       3d/compare-eax-and 0/imm32/false
    25967       74/jump-if-= break/disp8
    25968       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
    25969     }
    25970     # if both are floats, abort
    25971     {
    25972       (simple-mu-type? %edx 0xf)  # float => eax
    25973       3d/compare-eax-and 0/imm32/false
    25974       74/jump-if-= break/disp8
    25975       (simple-mu-type? %ecx 0xf)  # float => eax
    25976       3d/compare-eax-and 0/imm32/false
    25977       74/jump-if-= break/disp8
    25978       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
    25979     }
    25980 $check-mu-convert-stmt:end:
    25981     # . restore registers
    25982     5f/pop-to-edi
    25983     5e/pop-to-esi
    25984     5a/pop-to-edx
    25985     59/pop-to-ecx
    25986     58/pop-to-eax
    25987     # . epilogue
    25988     89/<- %esp 5/r32/ebp
    25989     5d/pop-to-ebp
    25990     c3/return
    25991
    25992 $check-mu-convert-stmt:error-no-inout:
    25993     (write-buffered *(ebp+0x10) "fn ")
    25994     8b/-> *(ebp+0xc) 0/r32/eax
    25995     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25996     (write-buffered *(ebp+0x10) %eax)
    25997     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
    25998     (flush *(ebp+0x10))
    25999     (stop *(ebp+0x14) 1)
    26000     # never gets here
    26001
    26002 $check-mu-convert-stmt:error-too-many-inouts:
    26003     (write-buffered *(ebp+0x10) "fn ")
    26004     8b/-> *(ebp+0xc) 0/r32/eax
    26005     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26006     (write-buffered *(ebp+0x10) %eax)
    26007     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
    26008     (flush *(ebp+0x10))
    26009     (stop *(ebp+0x14) 1)
    26010     # never gets here
    26011
    26012 $check-mu-convert-stmt:error-no-output:
    26013     (write-buffered *(ebp+0x10) "fn ")
    26014     8b/-> *(ebp+0xc) 0/r32/eax
    26015     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26016     (write-buffered *(ebp+0x10) %eax)
    26017     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
    26018     (flush *(ebp+0x10))
    26019     (stop *(ebp+0x14) 1)
    26020     # never gets here
    26021
    26022 $check-mu-convert-stmt:error-output-not-in-register:
    26023     (write-buffered *(ebp+0x10) "fn ")
    26024     8b/-> *(ebp+0xc) 0/r32/eax
    26025     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26026     (write-buffered *(ebp+0x10) %eax)
    26027     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26028     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26029     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26030     (write-buffered *(ebp+0x10) %eax)
    26031     (write-buffered *(ebp+0x10) "' not in a register\n")
    26032     (flush *(ebp+0x10))
    26033     (stop *(ebp+0x14) 1)
    26034     # never gets here
    26035
    26036 $check-mu-convert-stmt:error-too-many-outputs:
    26037     (write-buffered *(ebp+0x10) "fn ")
    26038     8b/-> *(ebp+0xc) 0/r32/eax
    26039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26040     (write-buffered *(ebp+0x10) %eax)
    26041     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
    26042     (flush *(ebp+0x10))
    26043     (stop *(ebp+0x14) 1)
    26044     # never gets here
    26045
    26046 $check-mu-convert-stmt:error-invalid-inout-type:
    26047     (write-buffered *(ebp+0x10) "fn ")
    26048     8b/-> *(ebp+0xc) 0/r32/eax
    26049     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26050     (write-buffered *(ebp+0x10) %eax)
    26051     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
    26052     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    26053     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26054     (write-buffered *(ebp+0x10) %eax)
    26055     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26056     (flush *(ebp+0x10))
    26057     (stop *(ebp+0x14) 1)
    26058     # never gets here
    26059
    26060 $check-mu-convert-stmt:error-invalid-output-type:
    26061     (write-buffered *(ebp+0x10) "fn ")
    26062     8b/-> *(ebp+0xc) 0/r32/eax
    26063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26064     (write-buffered *(ebp+0x10) %eax)
    26065     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26066     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26067     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26068     (write-buffered *(ebp+0x10) %eax)
    26069     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26070     (flush *(ebp+0x10))
    26071     (stop *(ebp+0x14) 1)
    26072     # never gets here
    26073
    26074 $check-mu-convert-stmt:error-int-to-int:
    26075     (write-buffered *(ebp+0x10) "fn ")
    26076     8b/-> *(ebp+0xc) 0/r32/eax
    26077     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26078     (write-buffered *(ebp+0x10) %eax)
    26079     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
    26080     (flush *(ebp+0x10))
    26081     (stop *(ebp+0x14) 1)
    26082     # never gets here
    26083
    26084 $check-mu-convert-stmt:error-float-to-float:
    26085     (write-buffered *(ebp+0x10) "fn ")
    26086     8b/-> *(ebp+0xc) 0/r32/eax
    26087     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26088     (write-buffered *(ebp+0x10) %eax)
    26089     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
    26090     (flush *(ebp+0x10))
    26091     (stop *(ebp+0x14) 1)
    26092     # never gets here
    26093
    26094 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    26095     # . prologue
    26096     55/push-ebp
    26097     89/<- %ebp 4/r32/esp
    26098     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
    26099     68/push 0/imm32
    26100     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
    26101     81 5/subop/subtract %esp 0x60/imm32
    26102     68/push 0x60/imm32/size
    26103     68/push 0/imm32/read
    26104     68/push 0/imm32/write
    26105     # save a pointer to type-parameters-storage at type-parameters
    26106     89/<- *(ebp-4) 4/r32/esp
    26107     (clear-stream *(ebp-4))
    26108     # . save registers
    26109     50/push-eax
    26110     51/push-ecx
    26111     52/push-edx
    26112     53/push-ebx
    26113     56/push-esi
    26114     57/push-edi
    26115     # esi = stmt
    26116     8b/-> *(ebp+8) 6/r32/esi
    26117     # edi = callee
    26118     8b/-> *(ebp+0xc) 7/r32/edi
    26119     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
    26120     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    26121     89/<- %ecx 0/r32/eax
    26122     # var expected/edx: (addr list var) = lookup(f->inouts)
    26123     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
    26124     89/<- %edx 0/r32/eax
    26125     {
    26126 $check-mu-call:check-for-inouts:
    26127       # if (inouts == 0) break
    26128       81 7/subop/compare %ecx 0/imm32
    26129       0f 84/jump-if-= break/disp32
    26130       # if (expected == 0) error
    26131       81 7/subop/compare %edx 0/imm32
    26132       0f 84/jump-if-= break/disp32
    26133 $check-mu-call:check-null-addr:
    26134       # if (inouts->value->name == "0") continue
    26135       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26136       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26137       (string-equal? %eax "0")  # => eax
    26138       3d/compare-eax-and 0/imm32/false
    26139       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
    26140 $check-mu-call:check-inout-type:
    26141       # var t/ebx: (addr type-tree) = inouts->value->type
    26142       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26143       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26144       89/<- %ebx 0/r32/eax
    26145       # if (inouts->is-deref?) t = t->right
    26146       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26147       {
    26148         74/jump-if-= break/disp8
    26149         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26150         89/<- %ebx 0/r32/eax
    26151         # if t->right is null, t = t->left
    26152         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
    26153         75/jump-if-!= break/disp8
    26154         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    26155         89/<- %ebx 0/r32/eax
    26156       }
    26157       # var v2/eax: (addr v) = lookup(expected->value)
    26158       (lookup *edx *(edx+4))  # List-value List-value => eax
    26159       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26160       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26161       # if (t != t2) error
    26162       (type-match? %eax %ebx *(ebp-4))  # => eax
    26163       3d/compare-eax-and 0/imm32/false
    26164       {
    26165         0f 85/jump-if-!= break/disp32
    26166         (write-buffered *(ebp+0x14) "fn ")
    26167         8b/-> *(ebp+0x10) 0/r32/eax
    26168         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26169         (write-buffered *(ebp+0x14) %eax)
    26170         (write-buffered *(ebp+0x14) ": call ")
    26171         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26172         (write-buffered *(ebp+0x14) %eax)
    26173         (write-buffered *(ebp+0x14) ": type for inout '")
    26174         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26175         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26176         (write-buffered *(ebp+0x14) %eax)
    26177         (write-buffered *(ebp+0x14) "' is not right\n")
    26178         (flush *(ebp+0x14))
    26179         (stop *(ebp+0x18) 1)
    26180       }
    26181 $check-mu-call:continue-to-next-inout:
    26182       # inouts = lookup(inouts->next)
    26183       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26184       89/<- %ecx 0/r32/eax
    26185       # expected = lookup(expected->next)
    26186       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26187       89/<- %edx 0/r32/eax
    26188       #
    26189       e9/jump loop/disp32
    26190     }
    26191 $check-mu-call:check-inout-count:
    26192     # if (inouts == expected) proceed
    26193     39/compare %ecx 2/r32/edx
    26194     {
    26195       0f 84/jump-if-= break/disp32
    26196       # exactly one of the two is null
    26197       # if (inouts == 0) error("too many inouts")
    26198       {
    26199         81 7/subop/compare %ecx 0/imm32
    26200         0f 84/jump-if-= break/disp32
    26201         (write-buffered *(ebp+0x14) "fn ")
    26202         8b/-> *(ebp+0x10) 0/r32/eax
    26203         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26204         (write-buffered *(ebp+0x14) %eax)
    26205         (write-buffered *(ebp+0x14) ": call ")
    26206         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26207         (write-buffered *(ebp+0x14) %eax)
    26208         (write-buffered *(ebp+0x14) ": too many inouts\n")
    26209         (flush *(ebp+0x14))
    26210         (stop *(ebp+0x18) 1)
    26211       }
    26212       # if (expected == 0) error("too few inouts")
    26213       {
    26214         81 7/subop/compare %edx 0/imm32
    26215         0f 84/jump-if-= break/disp32
    26216         (write-buffered *(ebp+0x14) "fn ")
    26217         8b/-> *(ebp+0x10) 0/r32/eax
    26218         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26219         (write-buffered *(ebp+0x14) %eax)
    26220         (write-buffered *(ebp+0x14) ": call ")
    26221         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26222         (write-buffered *(ebp+0x14) %eax)
    26223         (write-buffered *(ebp+0x14) ": too few inouts\n")
    26224         (flush *(ebp+0x14))
    26225         (stop *(ebp+0x18) 1)
    26226       }
    26227     }
    26228 $check-mu-call:check-outputs:
    26229     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
    26230     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    26231     89/<- %ecx 0/r32/eax
    26232     # var expected/edx: (addr list var) = lookup(f->outputs)
    26233     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
    26234     89/<- %edx 0/r32/eax
    26235     {
    26236 $check-mu-call:check-for-outputs:
    26237       # if (outputs == 0) break
    26238       81 7/subop/compare %ecx 0/imm32
    26239       0f 84/jump-if-= break/disp32
    26240       # if (expected == 0) error
    26241       81 7/subop/compare %edx 0/imm32
    26242       0f 84/jump-if-= break/disp32
    26243 $check-mu-call:check-output-type:
    26244       # var v/eax: (addr v) = lookup(outputs->value)
    26245       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26246       # var t/ebx: (addr type-tree) = lookup(v->type)
    26247       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26248       89/<- %ebx 0/r32/eax
    26249       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
    26250       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26251       {
    26252         74/jump-if-= break/disp8
    26253         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26254         89/<- %ebx 0/r32/eax
    26255       }
    26256       # var v2/eax: (addr v) = lookup(expected->value)
    26257       (lookup *edx *(edx+4))  # List-value List-value => eax
    26258       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26259       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26260       # if (t != t2) error
    26261       (type-match? %eax %ebx *(ebp-4))  # => eax
    26262       3d/compare-eax-and 0/imm32/false
    26263       {
    26264         0f 85/jump-if-!= break/disp32
    26265         (write-buffered *(ebp+0x14) "fn ")
    26266         8b/-> *(ebp+0x10) 0/r32/eax
    26267         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26268         (write-buffered *(ebp+0x14) %eax)
    26269         (write-buffered *(ebp+0x14) ": call ")
    26270         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26271         (write-buffered *(ebp+0x14) %eax)
    26272         (write-buffered *(ebp+0x14) ": type for output '")
    26273         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26274         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26275         (write-buffered *(ebp+0x14) %eax)
    26276         (write-buffered *(ebp+0x14) "' is not right\n")
    26277         (flush *(ebp+0x14))
    26278         (stop *(ebp+0x18) 1)
    26279       }
    26280 $check-mu-call:check-output-register:
    26281       # var v/eax: (addr v) = lookup(outputs->value)
    26282       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26283       # var r/ebx: (addr array byte) = lookup(v->register)
    26284       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26285       89/<- %ebx 0/r32/eax
    26286       # if (r == 0) error
    26287       3d/compare-eax-and 0/imm32
    26288       {
    26289         0f 85/jump-if-!= break/disp32
    26290         (write-buffered *(ebp+0x14) "fn ")
    26291         8b/-> *(ebp+0x10) 0/r32/eax
    26292         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26293         (write-buffered *(ebp+0x14) %eax)
    26294         (write-buffered *(ebp+0x14) ": call ")
    26295         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26296         (write-buffered *(ebp+0x14) %eax)
    26297         (write-buffered *(ebp+0x14) ": output '")
    26298         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26299         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26300         (write-buffered *(ebp+0x14) %eax)
    26301         (write-buffered *(ebp+0x14) "' is not in a register\n")
    26302         (flush *(ebp+0x14))
    26303         (stop *(ebp+0x18) 1)
    26304       }
    26305       # var v2/eax: (addr v) = lookup(expected->value)
    26306       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
    26307       # var r2/eax: (addr array byte) = lookup(v2->register)
    26308       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26309       # if (r != r2) error
    26310       (string-equal? %eax %ebx)  # => eax
    26311       3d/compare-eax-and 0/imm32/false
    26312       {
    26313         0f 85/jump-if-!= break/disp32
    26314         (write-buffered *(ebp+0x14) "fn ")
    26315         8b/-> *(ebp+0x10) 0/r32/eax
    26316         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26317         (write-buffered *(ebp+0x14) %eax)
    26318         (write-buffered *(ebp+0x14) ": call ")
    26319         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26320         (write-buffered *(ebp+0x14) %eax)
    26321         (write-buffered *(ebp+0x14) ": register for output '")
    26322         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26323         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26324         (write-buffered *(ebp+0x14) %eax)
    26325         (write-buffered *(ebp+0x14) "' is not right\n")
    26326         (flush *(ebp+0x14))
    26327         (stop *(ebp+0x18) 1)
    26328       }
    26329 $check-mu-call:continue-to-next-output:
    26330       # outputs = lookup(outputs->next)
    26331       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26332       89/<- %ecx 0/r32/eax
    26333       # expected = lookup(expected->next)
    26334       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26335       89/<- %edx 0/r32/eax
    26336       #
    26337       e9/jump loop/disp32
    26338     }
    26339 $check-mu-call:check-output-count:
    26340     # if (outputs == expected) proceed
    26341     39/compare %ecx 2/r32/edx
    26342     {
    26343       0f 84/jump-if-= break/disp32
    26344       # exactly one of the two is null
    26345       # if (outputs == 0) error("too many outputs")
    26346       {
    26347         81 7/subop/compare %ecx 0/imm32
    26348         0f 84/jump-if-= break/disp32
    26349         (write-buffered *(ebp+0x14) "fn ")
    26350         8b/-> *(ebp+0x10) 0/r32/eax
    26351         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26352         (write-buffered *(ebp+0x14) %eax)
    26353         (write-buffered *(ebp+0x14) ": call ")
    26354         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26355         (write-buffered *(ebp+0x14) %eax)
    26356         (write-buffered *(ebp+0x14) ": too many outputs\n")
    26357         (flush *(ebp+0x14))
    26358         (stop *(ebp+0x18) 1)
    26359       }
    26360       # if (expected == 0) error("too few outputs")
    26361       {
    26362         81 7/subop/compare %edx 0/imm32
    26363         0f 84/jump-if-= break/disp32
    26364         (write-buffered *(ebp+0x14) "fn ")
    26365         8b/-> *(ebp+0x10) 0/r32/eax
    26366         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26367         (write-buffered *(ebp+0x14) %eax)
    26368         (write-buffered *(ebp+0x14) ": call ")
    26369         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26370         (write-buffered *(ebp+0x14) %eax)
    26371         (write-buffered *(ebp+0x14) ": too few outputs\n")
    26372         (flush *(ebp+0x14))
    26373         (stop *(ebp+0x18) 1)
    26374       }
    26375     }
    26376 $check-mu-call:end:
    26377     # . restore registers
    26378     5f/pop-to-edi
    26379     5e/pop-to-esi
    26380     5b/pop-to-ebx
    26381     5a/pop-to-edx
    26382     59/pop-to-ecx
    26383     58/pop-to-eax
    26384     # . reclaim locals exclusively on the stack
    26385     81 0/subop/add %esp 0x70/imm32
    26386     # . epilogue
    26387     89/<- %esp 5/r32/ebp
    26388     5d/pop-to-ebp
    26389     c3/return
    26390
    26391 # like type-equal? but takes literals type parameters into account
    26392 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26393     # . prologue
    26394     55/push-ebp
    26395     89/<- %ebp 4/r32/esp
    26396     # if (call is literal and def is numberlike) return true
    26397     {
    26398 $type-match?:check-literal-int:
    26399       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
    26400       3d/compare-eax-and 0/imm32/false
    26401       74/jump-if-= break/disp8
    26402       (mu-numberlike-output? *(ebp+8))  # => eax
    26403       3d/compare-eax-and 0/imm32/false
    26404       74/jump-if-= break/disp8
    26405       b8/copy-to-eax 1/imm32/true
    26406       e9/jump $type-match?:end/disp32
    26407     }
    26408     # if (call is literal-string and def is string) return true
    26409     {
    26410 $type-match?:check-literal-string:
    26411       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
    26412       3d/compare-eax-and 0/imm32/false
    26413       74/jump-if-= break/disp8
    26414       (mu-string-type? *(ebp+8))  # => eax
    26415       3d/compare-eax-and 0/imm32/false
    26416       74/jump-if-= break/disp8
    26417       b8/copy-to-eax 1/imm32/true
    26418       e9/jump $type-match?:end/disp32
    26419     }
    26420 $type-match?:baseline:
    26421     # otherwise fall back
    26422     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    26423 $type-match?:end:
    26424     # . epilogue
    26425     89/<- %esp 5/r32/ebp
    26426     5d/pop-to-ebp
    26427     c3/return
    26428
    26429 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26430     # . prologue
    26431     55/push-ebp
    26432     89/<- %ebp 4/r32/esp
    26433     # . save registers
    26434     51/push-ecx
    26435     52/push-edx
    26436     53/push-ebx
    26437     # ecx = def
    26438     8b/-> *(ebp+8) 1/r32/ecx
    26439     # edx = call
    26440     8b/-> *(ebp+0xc) 2/r32/edx
    26441 $type-component-match?:compare-addr:
    26442     # if (def == call) return true
    26443     8b/-> %ecx 0/r32/eax  # Var-type
    26444     39/compare %edx 0/r32/eax  # Var-type
    26445     b8/copy-to-eax 1/imm32/true
    26446     0f 84/jump-if-= $type-component-match?:end/disp32
    26447     # if (def == 0) return false
    26448     b8/copy-to-eax 0/imm32/false
    26449     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
    26450     0f 84/jump-if-= $type-component-match?:end/disp32
    26451     # if (call == 0) return false
    26452     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
    26453     0f 84/jump-if-= $type-component-match?:end/disp32
    26454     # if def is a type parameter, just check in type-parameters
    26455     {
    26456 $type-component-match?:check-type-parameter:
    26457       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26458       74/jump-if-= break/disp8
    26459       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
    26460       75/jump-if-!= break/disp8
    26461 $type-component-match?:type-parameter:
    26462       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
    26463       e9/jump $type-component-match?:end/disp32
    26464     }
    26465     # if def is a list containing just a type parameter, just check in type-parameters
    26466     {
    26467 $type-component-match?:check-list-type-parameter:
    26468       # if def is a list..
    26469       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26470       75/jump-if-!= break/disp8
    26471       #   ..that's a singleton
    26472       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
    26473       75/jump-if-!= break/disp8
    26474       #   ..and whose head is a type parameter
    26475       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26476       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26477       74/jump-if-= break/disp8
    26478       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
    26479       75/jump-if-!= break/disp8
    26480 $type-component-match?:list-type-parameter:
    26481       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
    26482       e9/jump $type-component-match?:end/disp32
    26483     }
    26484 $type-component-match?:compare-atom-state:
    26485     # if (def->is-atom? != call->is-atom?) return false
    26486     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26487     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26488     b8/copy-to-eax 0/imm32/false
    26489     0f 85/jump-if-!= $type-component-match?:end/disp32
    26490     # if def->is-atom? return (def->value == call->value)
    26491     {
    26492 $type-component-match?:check-atom:
    26493       81 7/subop/compare %ebx 0/imm32/false
    26494       74/jump-if-= break/disp8
    26495 $type-component-match?:is-atom:
    26496       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26497       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26498       0f 94/set-if-= %al
    26499       81 4/subop/and %eax 0xff/imm32
    26500       e9/jump $type-component-match?:end/disp32
    26501     }
    26502 $type-component-match?:check-left:
    26503     # if (!type-component-match?(def->left, call->left)) return false
    26504     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26505     89/<- %ebx 0/r32/eax
    26506     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26507     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26508     3d/compare-eax-and 0/imm32/false
    26509     74/jump-if-= $type-component-match?:end/disp8
    26510 $type-component-match?:check-right:
    26511     # return type-component-match?(def->right, call->right)
    26512     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26513     89/<- %ebx 0/r32/eax
    26514     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26515     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26516 $type-component-match?:end:
    26517     # . restore registers
    26518     5b/pop-to-ebx
    26519     5a/pop-to-edx
    26520     59/pop-to-ecx
    26521     # . epilogue
    26522     89/<- %esp 5/r32/ebp
    26523     5d/pop-to-ebp
    26524     c3/return
    26525
    26526 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
    26527     # . prologue
    26528     55/push-ebp
    26529     89/<- %ebp 4/r32/esp
    26530     # . save registers
    26531     51/push-ecx
    26532     #
    26533     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
    26534     # if parameter wasn't saved, save it
    26535     {
    26536       81 7/subop/compare *eax 0/imm32
    26537       75/jump-if-!= break/disp8
    26538       8b/-> *(ebp+0x10) 1/r32/ecx
    26539       89/<- *eax 1/r32/ecx
    26540     }
    26541     #
    26542     (type-equal? *(ebp+0x10) *eax)  # => eax
    26543 $type-parameter-match?:end:
    26544     # . restore registers
    26545     59/pop-to-ecx
    26546     # . epilogue
    26547     89/<- %esp 5/r32/ebp
    26548     5d/pop-to-ebp
    26549     c3/return
    26550
    26551 size-of:  # v: (addr var) -> result/eax: int
    26552     # . prologue
    26553     55/push-ebp
    26554     89/<- %ebp 4/r32/esp
    26555     # . save registers
    26556     51/push-ecx
    26557     # var t/ecx: (addr type-tree) = lookup(v->type)
    26558     8b/-> *(ebp+8) 1/r32/ecx
    26559 #?     (write-buffered Stderr "size-of ")
    26560 #?     (write-int32-hex-buffered Stderr %ecx)
    26561 #?     (write-buffered Stderr Newline)
    26562 #?     (write-buffered Stderr "type allocid: ")
    26563 #?     (write-int32-hex-buffered Stderr *(ecx+8))
    26564 #?     (write-buffered Stderr Newline)
    26565 #?     (flush Stderr)
    26566     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26567     89/<- %ecx 0/r32/eax
    26568     # if mu-array?(t) return size-of-array(t)
    26569     {
    26570       (mu-array? %ecx)  # => eax
    26571       3d/compare-eax-and 0/imm32/false
    26572       74/jump-if-= break/disp8
    26573       (size-of-array %ecx)  # => eax
    26574       eb/jump $size-of:end/disp8
    26575     }
    26576     # if mu-stream?(t) return size-of-stream(t)
    26577     {
    26578       (mu-stream? %ecx)  # => eax
    26579       3d/compare-eax-and 0/imm32/false
    26580       74/jump-if-= break/disp8
    26581       (size-of-stream %ecx)  # => eax
    26582       eb/jump $size-of:end/disp8
    26583     }
    26584     # if (!t->is-atom?) t = lookup(t->left)
    26585     {
    26586       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26587       75/jump-if-!= break/disp8
    26588       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26589       89/<- %ecx 0/r32/eax
    26590     }
    26591     # TODO: assert t->is-atom?
    26592     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26593 $size-of:end:
    26594     # . restore registers
    26595     59/pop-to-ecx
    26596     # . epilogue
    26597     89/<- %esp 5/r32/ebp
    26598     5d/pop-to-ebp
    26599     c3/return
    26600
    26601 size-of-deref:  # v: (addr var) -> result/eax: int
    26602     # . prologue
    26603     55/push-ebp
    26604     89/<- %ebp 4/r32/esp
    26605     # . save registers
    26606     51/push-ecx
    26607     # var t/ecx: (addr type-tree) = lookup(v->type)
    26608     8b/-> *(ebp+8) 1/r32/ecx
    26609     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26610     89/<- %ecx 0/r32/eax
    26611     # TODO: assert(t is an addr)
    26612     # t = lookup(t->right)
    26613     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26614     89/<- %ecx 0/r32/eax
    26615     # if mu-array?(t) return size-of-array(t)
    26616     {
    26617       (mu-array? %ecx)  # => eax
    26618       3d/compare-eax-and 0/imm32/false
    26619       74/jump-if-= break/disp8
    26620       (size-of-array %ecx)  # => eax
    26621       eb/jump $size-of-deref:end/disp8
    26622     }
    26623     # if mu-stream?(t) return size-of-stream(t)
    26624     {
    26625       (mu-stream? %ecx)  # => eax
    26626       3d/compare-eax-and 0/imm32/false
    26627       74/jump-if-= break/disp8
    26628       (size-of-stream %ecx)  # => eax
    26629       eb/jump $size-of-deref:end/disp8
    26630     }
    26631     # if (!t->is-atom?) t = lookup(t->left)
    26632     {
    26633       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26634       75/jump-if-!= break/disp8
    26635       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26636       89/<- %ecx 0/r32/eax
    26637     }
    26638     # TODO: assert t->is-atom?
    26639     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26640 $size-of-deref:end:
    26641     # . restore registers
    26642     59/pop-to-ecx
    26643     # . epilogue
    26644     89/<- %esp 5/r32/ebp
    26645     5d/pop-to-ebp
    26646     c3/return
    26647
    26648 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
    26649     # . prologue
    26650     55/push-ebp
    26651     89/<- %ebp 4/r32/esp
    26652     # . save registers
    26653     51/push-ecx
    26654     # ecx = t
    26655     8b/-> *(ebp+8) 1/r32/ecx
    26656     # if t->is-atom?, return false
    26657     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26658     75/jump-if-!= $mu-array?:return-false/disp8
    26659     # if !t->left->is-atom?, return false
    26660     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26661     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26662     74/jump-if-= $mu-array?:return-false/disp8
    26663     # return t->left->value == array
    26664     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
    26665     0f 94/set-if-= %al
    26666     81 4/subop/and %eax 0xff/imm32
    26667     eb/jump $mu-array?:end/disp8
    26668 $mu-array?:return-false:
    26669     b8/copy-to-eax 0/imm32/false
    26670 $mu-array?:end:
    26671     # . restore registers
    26672     59/pop-to-ecx
    26673     # . epilogue
    26674     89/<- %esp 5/r32/ebp
    26675     5d/pop-to-ebp
    26676     c3/return
    26677
    26678 # size of a statically allocated array where the size is part of the type expression
    26679 size-of-array:  # a: (addr type-tree) -> result/eax: int
    26680     # . prologue
    26681     55/push-ebp
    26682     89/<- %ebp 4/r32/esp
    26683     # . save registers
    26684     51/push-ecx
    26685     52/push-edx
    26686     #
    26687     8b/-> *(ebp+8) 1/r32/ecx
    26688     # TODO: assert that a->left is 'array'
    26689     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26690     89/<- %ecx 0/r32/eax
    26691     # var elem-type/edx: type-id = a->right->left->value
    26692     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26693     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
    26694     # TODO: assert that a->right->right->left->value == size
    26695     # var array-size/ecx: int = a->right->right->left->value-size
    26696     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26697     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26698     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
    26699     # return 4 + array-size * size-of(elem-type)
    26700     (size-of-type-id-as-array-element %edx)  # => eax
    26701     f7 4/subop/multiply-into-edx-eax %ecx
    26702     05/add-to-eax 4/imm32  # for array size
    26703     # TODO: check edx for overflow
    26704 $size-of-array:end:
    26705     # . restore registers
    26706     5a/pop-to-edx
    26707     59/pop-to-ecx
    26708     # . epilogue
    26709     89/<- %esp 5/r32/ebp
    26710     5d/pop-to-ebp
    26711     c3/return
    26712
    26713 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
    26714     # . prologue
    26715     55/push-ebp
    26716     89/<- %ebp 4/r32/esp
    26717     # . save registers
    26718     51/push-ecx
    26719     # ecx = t
    26720     8b/-> *(ebp+8) 1/r32/ecx
    26721     # if t->is-atom?, return false
    26722     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26723     75/jump-if-!= $mu-stream?:return-false/disp8
    26724     # if !t->left->is-atom?, return false
    26725     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26726     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26727     74/jump-if-= $mu-stream?:return-false/disp8
    26728     # return t->left->value == stream
    26729     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
    26730     0f 94/set-if-= %al
    26731     81 4/subop/and %eax 0xff/imm32
    26732     eb/jump $mu-stream?:end/disp8
    26733 $mu-stream?:return-false:
    26734     b8/copy-to-eax 0/imm32/false
    26735 $mu-stream?:end:
    26736     # . restore registers
    26737     59/pop-to-ecx
    26738     # . epilogue
    26739     89/<- %esp 5/r32/ebp
    26740     5d/pop-to-ebp
    26741     c3/return
    26742
    26743 # size of a statically allocated stream where the size is part of the type expression
    26744 size-of-stream:  # a: (addr type-tree) -> result/eax: int
    26745     # . prologue
    26746     55/push-ebp
    26747     89/<- %ebp 4/r32/esp
    26748     #
    26749     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
    26750     05/add-to-eax 8/imm32  # for read/write pointers
    26751 $size-of-stream:end:
    26752     # . epilogue
    26753     89/<- %esp 5/r32/ebp
    26754     5d/pop-to-ebp
    26755     c3/return
    26756
    26757 size-of-type-id:  # t: type-id -> result/eax: int
    26758     # . prologue
    26759     55/push-ebp
    26760     89/<- %ebp 4/r32/esp
    26761     # . save registers
    26762     51/push-ecx
    26763     # var out/ecx: (handle typeinfo)
    26764     68/push 0/imm32
    26765     68/push 0/imm32
    26766     89/<- %ecx 4/r32/esp
    26767     # eax = t
    26768     8b/-> *(ebp+8) 0/r32/eax
    26769     # if t is a literal, return 0
    26770     3d/compare-eax-and 0/imm32
    26771     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
    26772     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    26773     3d/compare-eax-and 8/imm32/byte
    26774     {
    26775       75/jump-if-!= break/disp8
    26776       b8/copy-to-eax 4/imm32
    26777       eb/jump $size-of-type-id:end/disp8
    26778     }
    26779     # if t is a handle, return 8
    26780     3d/compare-eax-and 4/imm32/handle
    26781     {
    26782       75/jump-if-!= break/disp8
    26783       b8/copy-to-eax 8/imm32
    26784       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26785     }
    26786     # if t is a slice, return 8
    26787     3d/compare-eax-and 0xc/imm32/slice
    26788     {
    26789       75/jump-if-!= break/disp8
    26790       b8/copy-to-eax 8/imm32
    26791       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26792     }
    26793     # if t is a user-defined type, return its size
    26794     # TODO: support non-atom type
    26795     (find-typeinfo %eax %ecx)
    26796     {
    26797       81 7/subop/compare *ecx 0/imm32
    26798       74/jump-if-= break/disp8
    26799 $size-of-type-id:user-defined:
    26800       (lookup *ecx *(ecx+4))  # => eax
    26801       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    26802       eb/jump $size-of-type-id:end/disp8
    26803     }
    26804     # otherwise return the word size
    26805     b8/copy-to-eax 4/imm32
    26806 $size-of-type-id:end:
    26807     # . reclaim locals
    26808     81 0/subop/add %esp 8/imm32
    26809     # . restore registers
    26810     59/pop-to-ecx
    26811     # . epilogue
    26812     89/<- %esp 5/r32/ebp
    26813     5d/pop-to-ebp
    26814     c3/return
    26815
    26816 # Minor violation of our type system since it returns an addr. But we could
    26817 # replace it with a handle some time.
    26818 # Returns null if t is an atom.
    26819 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
    26820     # . prologue
    26821     55/push-ebp
    26822     89/<- %ebp 4/r32/esp
    26823     # . save registers
    26824     51/push-ecx
    26825     # eax = 0
    26826     b8/copy-to-eax 0/imm32
    26827     # ecx = t
    26828     8b/-> *(ebp+8) 1/r32/ecx
    26829 $type-tail:check-atom:
    26830     # if t->is-atom? return 0
    26831     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26832     0f 85/jump-if-!= $type-tail:end/disp32
    26833     # var tail = t->right
    26834     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26835     89/<- %ecx 0/r32/eax
    26836 $type-tail:check-singleton:
    26837     # if (tail->right == 0) return tail->left
    26838     {
    26839       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
    26840       75/jump-if-!= break/disp8
    26841       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26842       e9/jump $type-tail:end/disp32
    26843     }
    26844     # if tail->right->left is an array-capacity, return tail->left
    26845     {
    26846 $type-tail:check-array-capacity:
    26847       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26848       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26849       75/jump-if-!= break/disp8
    26850 $type-tail:check-array-capacity-1:
    26851       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26852       3d/compare-eax-and 0/imm32
    26853       74/jump-if-= break/disp8
    26854 $type-tail:check-array-capacity-2:
    26855       (simple-mu-type? %eax 9)  # array-capacity => eax
    26856       3d/compare-eax-and 0/imm32/false
    26857       74/jump-if-= break/disp8
    26858 $type-tail:array-capacity:
    26859       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26860       eb/jump $type-tail:end/disp8
    26861     }
    26862 $type-tail:check-compound-left:
    26863     # if !tail->left->is-atom? return tail->left
    26864     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26865     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26866     74/jump-if-= $type-tail:end/disp8
    26867 $type-tail:return-tail:
    26868     # return tail
    26869     89/<- %eax 1/r32/ecx
    26870 $type-tail:end:
    26871     # . restore registers
    26872     59/pop-to-ecx
    26873     # . epilogue
    26874     89/<- %esp 5/r32/ebp
    26875     5d/pop-to-ebp
    26876     c3/return
    26877
    26878 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    26879     # . prologue
    26880     55/push-ebp
    26881     89/<- %ebp 4/r32/esp
    26882     # . save registers
    26883     51/push-ecx
    26884     52/push-edx
    26885     53/push-ebx
    26886     # ecx = a
    26887     8b/-> *(ebp+8) 1/r32/ecx
    26888     # edx = b
    26889     8b/-> *(ebp+0xc) 2/r32/edx
    26890 $type-equal?:compare-addr:
    26891     # if (a == b) return true
    26892     8b/-> %ecx 0/r32/eax  # Var-type
    26893     39/compare %edx 0/r32/eax  # Var-type
    26894     b8/copy-to-eax 1/imm32/true
    26895     0f 84/jump-if-= $type-equal?:end/disp32
    26896 $type-equal?:compare-null-a:
    26897     # if (a == 0) return false
    26898     b8/copy-to-eax 0/imm32/false
    26899     81 7/subop/compare %ecx 0/imm32
    26900     0f 84/jump-if-= $type-equal?:end/disp32
    26901 $type-equal?:compare-null-b:
    26902     # if (b == 0) return false
    26903     81 7/subop/compare %edx 0/imm32
    26904     0f 84/jump-if-= $type-equal?:end/disp32
    26905 $type-equal?:compare-atom-state:
    26906     # if (a->is-atom? != b->is-atom?) return false
    26907     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26908     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26909     b8/copy-to-eax 0/imm32/false
    26910     0f 85/jump-if-!= $type-equal?:end/disp32
    26911     # if a->is-atom? return (a->value == b->value)
    26912     {
    26913 $type-equal?:check-atom:
    26914       81 7/subop/compare %ebx 0/imm32/false
    26915       74/jump-if-= break/disp8
    26916 $type-equal?:is-atom:
    26917       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26918       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26919       0f 94/set-if-= %al
    26920       81 4/subop/and %eax 0xff/imm32
    26921       e9/jump $type-equal?:end/disp32
    26922     }
    26923 $type-equal?:check-left:
    26924     # if (!type-equal?(a->left, b->left)) return false
    26925     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26926     89/<- %ebx 0/r32/eax
    26927     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26928     (type-equal? %eax %ebx)  # => eax
    26929     3d/compare-eax-and 0/imm32/false
    26930     74/jump-if-= $type-equal?:end/disp8
    26931 $type-equal?:check-right:
    26932     # return type-equal?(a->right, b->right)
    26933     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26934     89/<- %ebx 0/r32/eax
    26935     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26936     (type-equal? %eax %ebx)  # => eax
    26937 $type-equal?:end:
    26938     # . restore registers
    26939     5b/pop-to-ebx
    26940     5a/pop-to-edx
    26941     59/pop-to-ecx
    26942     # . epilogue
    26943     89/<- %esp 5/r32/ebp
    26944     5d/pop-to-ebp
    26945     c3/return
    26946
    26947 #######################################################
    26948 # Code-generation
    26949 #######################################################
    26950
    26951 == data
    26952
    26953 # Global state added to each var record when performing code-generation.
    26954 Curr-local-stack-offset:  # (addr int)
    26955     0/imm32
    26956
    26957 == code
    26958
    26959 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
    26960 # getting type checks later in life.
    26961 # But we do need them for runtime checks, particularly array index bounds checks.
    26962 # So perhaps it's not worth taking them out. They're a safety net.
    26963
    26964 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    26965     # . prologue
    26966     55/push-ebp
    26967     89/<- %ebp 4/r32/esp
    26968     # . save registers
    26969     50/push-eax
    26970     # var curr/eax: (addr function) = *Program->functions
    26971     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    26972     {
    26973       # if (curr == null) break
    26974       3d/compare-eax-and 0/imm32
    26975       0f 84/jump-if-= break/disp32
    26976       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
    26977       # curr = lookup(curr->next)
    26978       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    26979       e9/jump loop/disp32
    26980     }
    26981 $emit-subx:end:
    26982     # . restore registers
    26983     58/pop-to-eax
    26984     # . epilogue
    26985     89/<- %esp 5/r32/ebp
    26986     5d/pop-to-ebp
    26987     c3/return
    26988
    26989 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    26990     # . prologue
    26991     55/push-ebp
    26992     89/<- %ebp 4/r32/esp
    26993     # some preprocessing
    26994     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
    26995     # . save registers
    26996     50/push-eax
    26997     51/push-ecx
    26998     52/push-edx
    26999     # initialize some global state
    27000     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
    27001     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
    27002     # ecx = f
    27003     8b/-> *(ebp+0xc) 1/r32/ecx
    27004     # var vars/edx: (stack (addr var) 256)
    27005     81 5/subop/subtract %esp 0xc00/imm32
    27006     68/push 0xc00/imm32/size
    27007     68/push 0/imm32/top
    27008     89/<- %edx 4/r32/esp
    27009     # var name/eax: (addr array byte) = lookup(f->name)
    27010     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    27011     #
    27012     (write-buffered *(ebp+8) %eax)
    27013     (write-buffered *(ebp+8) ":\n")
    27014     (emit-subx-prologue *(ebp+8))
    27015     # var body/eax: (addr block) = lookup(f->body)
    27016     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
    27017     #
    27018     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    27019     (emit-subx-epilogue *(ebp+8))
    27020     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
    27021     # been cleaned up
    27022 $emit-subx-function:end:
    27023     # . reclaim locals
    27024     81 0/subop/add %esp 0xc08/imm32
    27025     # . restore registers
    27026     5a/pop-to-edx
    27027     59/pop-to-ecx
    27028     58/pop-to-eax
    27029     # . epilogue
    27030     89/<- %esp 5/r32/ebp
    27031     5d/pop-to-ebp
    27032     c3/return
    27033
    27034 populate-mu-type-offsets-in-inouts:  # f: (addr function)
    27035     # . prologue
    27036     55/push-ebp
    27037     89/<- %ebp 4/r32/esp
    27038     # . save registers
    27039     50/push-eax
    27040     51/push-ecx
    27041     52/push-edx
    27042     53/push-ebx
    27043     57/push-edi
    27044     # var next-offset/edx: int = 8
    27045     ba/copy-to-edx 8/imm32
    27046     # var curr/ecx: (addr list var) = lookup(f->inouts)
    27047     8b/-> *(ebp+8) 1/r32/ecx
    27048     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    27049     89/<- %ecx 0/r32/eax
    27050     {
    27051 $populate-mu-type-offsets-in-inouts:loop:
    27052       81 7/subop/compare %ecx 0/imm32
    27053       74/jump-if-= break/disp8
    27054       # var v/ebx: (addr var) = lookup(curr->value)
    27055       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    27056       89/<- %ebx 0/r32/eax
    27057 #?       (lookup *ebx *(ebx+4))
    27058 #?       (write-buffered Stderr "setting offset of fn inout ")
    27059 #?       (write-buffered Stderr %eax)
    27060 #?       (write-buffered Stderr "@")
    27061 #?       (write-int32-hex-buffered Stderr %ebx)
    27062 #?       (write-buffered Stderr " to ")
    27063 #?       (write-int32-hex-buffered Stderr %edx)
    27064 #?       (write-buffered Stderr Newline)
    27065 #?       (flush Stderr)
    27066       # v->offset = next-offset
    27067       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
    27068       # next-offset += size-of(v)
    27069       (size-of %ebx)  # => eax
    27070       01/add-to %edx 0/r32/eax
    27071       # curr = lookup(curr->next)
    27072       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    27073       89/<- %ecx 0/r32/eax
    27074       #
    27075       eb/jump loop/disp8
    27076     }
    27077 $populate-mu-type-offsets-in-inouts:end:
    27078     # . restore registers
    27079     5f/pop-to-edi
    27080     5b/pop-to-ebx
    27081     5a/pop-to-edx
    27082     59/pop-to-ecx
    27083     58/pop-to-eax
    27084     # . epilogue
    27085     89/<- %esp 5/r32/ebp
    27086     5d/pop-to-ebp
    27087     c3/return
    27088
    27089 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)
    27090     # . prologue
    27091     55/push-ebp
    27092     89/<- %ebp 4/r32/esp
    27093     # . save registers
    27094     50/push-eax
    27095     51/push-ecx
    27096     53/push-ebx
    27097     56/push-esi
    27098     # esi = stmts
    27099     8b/-> *(ebp+0xc) 6/r32/esi
    27100     #
    27101     {
    27102 $emit-subx-stmt-list:loop:
    27103       81 7/subop/compare %esi 0/imm32
    27104       0f 84/jump-if-= break/disp32
    27105       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
    27106       (lookup *esi *(esi+4))  # List-value List-value => eax
    27107       89/<- %ecx 0/r32/eax
    27108       {
    27109 $emit-subx-stmt-list:check-for-block:
    27110         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    27111         75/jump-if-!= break/disp8
    27112 $emit-subx-stmt-list:block:
    27113         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27114       }
    27115       {
    27116 $emit-subx-stmt-list:check-for-stmt:
    27117         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    27118         0f 85/jump-if-!= break/disp32
    27119 $emit-subx-stmt-list:stmt1:
    27120         {
    27121           (mu-branch? %ecx)  # => eax
    27122           3d/compare-eax-and 0/imm32/false
    27123           0f 84/jump-if-= break/disp32
    27124 $emit-subx-stmt-list:branch-stmt:
    27125 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
    27150 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
    27177 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
    27193 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
    27231 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
    27250         }
    27251 $emit-subx-stmt-list:1-to-1:
    27252         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27253         e9/jump $emit-subx-stmt-list:continue/disp32
    27254       }
    27255       {
    27256 $emit-subx-stmt-list:check-for-var-def:
    27257         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
    27258         75/jump-if-!= break/disp8
    27259 $emit-subx-stmt-list:var-def:
    27260         (emit-subx-var-def *(ebp+8) %ecx)
    27261         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
    27262         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
    27263         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
    27264         #
    27265         eb/jump $emit-subx-stmt-list:continue/disp8
    27266       }
    27267       {
    27268 $emit-subx-stmt-list:check-for-reg-var-def:
    27269         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
    27270         0f 85/jump-if-!= break/disp32
    27271 $emit-subx-stmt-list:reg-var-def:
    27272         # TODO: ensure that there's exactly one output
    27273         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27274         # emit the instruction as usual
    27275         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27276         #
    27277         eb/jump $emit-subx-stmt-list:continue/disp8
    27278       }
    27279 $emit-subx-stmt-list:continue:
    27280       # TODO: raise an error on unrecognized Stmt-tag
    27281       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    27282       89/<- %esi 0/r32/eax
    27283       e9/jump loop/disp32
    27284     }
    27285 $emit-subx-stmt-list:emit-cleanup:
    27286     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
    27287 $emit-subx-stmt-list:clean-up:
    27288     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
    27289     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
    27290 $emit-subx-stmt-list:end:
    27291     # . restore registers
    27292     5e/pop-to-esi
    27293     5b/pop-to-ebx
    27294     59/pop-to-ecx
    27295     58/pop-to-eax
    27296     # . epilogue
    27297     89/<- %esp 5/r32/ebp
    27298     5d/pop-to-ebp
    27299     c3/return
    27300
    27301 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
    27302 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)
    27303     # . prologue
    27304     55/push-ebp
    27305     89/<- %ebp 4/r32/esp
    27306     # . save registers
    27307     50/push-eax
    27308     51/push-ecx
    27309     52/push-edx
    27310     # ecx = stmt
    27311     8b/-> *(ebp+0xc) 1/r32/ecx
    27312     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
    27313     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27314     # TODO: assert !sv->is-deref?
    27315     # var v/ecx: (addr var) = lookup(sv->value)
    27316     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27317     89/<- %ecx 0/r32/eax
    27318     # v->block-depth = *Curr-block-depth
    27319     8b/-> *Curr-block-depth 0/r32/eax
    27320     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    27321 #?     (write-buffered Stderr "var ")
    27322 #?     (lookup *ecx *(ecx+4))
    27323 #?     (write-buffered Stderr %eax)
    27324 #?     (write-buffered Stderr " at depth ")
    27325 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
    27326 #?     (write-buffered Stderr Newline)
    27327 #?     (flush Stderr)
    27328     # ensure that v is in a register
    27329     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    27330     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
    27331     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
    27332     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
    27333     89/<- %edx 0/r32/eax
    27334     3d/compare-eax-and 0/imm32/false
    27335     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27336     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
    27337     89/<- %edx 0/r32/eax
    27338     # check emit-spill?
    27339     3d/compare-eax-and 0/imm32/false
    27340     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27341     # TODO: assert(size-of(output) == 4)
    27342     # *Curr-local-stack-offset -= 4
    27343     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
    27344     # emit spill
    27345     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    27346     (emit-push-register *(ebp+8) %eax)
    27347 $push-output-and-maybe-emit-spill:push:
    27348     8b/-> *(ebp+0xc) 1/r32/ecx
    27349     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27350     # push(vars, {sv->value, emit-spill?})
    27351     (push *(ebp+0x10) *eax)  # Stmt-var-value
    27352     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
    27353     (push *(ebp+0x10) %edx)
    27354 $push-output-and-maybe-emit-spill:end:
    27355     # . restore registers
    27356     5a/pop-to-edx
    27357     59/pop-to-ecx
    27358     58/pop-to-eax
    27359     # . epilogue
    27360     89/<- %esp 5/r32/ebp
    27361     5d/pop-to-ebp
    27362     c3/return
    27363
    27364 $push-output-and-maybe-emit-spill:abort:
    27365     # error("var '" var->name "' initialized from an instruction must live in a register\n")
    27366     (write-buffered *(ebp+0x1c) "var '")
    27367     (write-buffered *(ebp+0x1c) *eax)  # Var-name
    27368     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
    27369     (flush *(ebp+0x1c))
    27370     (stop *(ebp+0x20) 1)
    27371     # never gets here
    27372
    27373 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
    27374     # . prologue
    27375     55/push-ebp
    27376     89/<- %ebp 4/r32/esp
    27377     # . save registers
    27378     50/push-eax
    27379     51/push-ecx
    27380     # ecx = stmt
    27381     8b/-> *(ebp+0xc) 1/r32/ecx
    27382     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
    27383     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27384     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27385     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    27386     # clean up until target block
    27387     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
    27388     # emit jump to target block
    27389     (emit-indent *(ebp+8) *Curr-block-depth)
    27390     (write-buffered *(ebp+8) "e9/jump ")
    27391     (write-buffered *(ebp+8) %eax)
    27392     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27393     (string-starts-with? %eax "break")
    27394     3d/compare-eax-and 0/imm32/false
    27395     {
    27396       74/jump-if-= break/disp8
    27397       (write-buffered *(ebp+8) ":break/disp32\n")
    27398       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
    27399     }
    27400     (write-buffered *(ebp+8) ":loop/disp32\n")
    27401 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
    27402     # . restore registers
    27403     59/pop-to-ecx
    27404     58/pop-to-eax
    27405     # . epilogue
    27406     89/<- %esp 5/r32/ebp
    27407     5d/pop-to-ebp
    27408     c3/return
    27409
    27410 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
    27411     # . prologue
    27412     55/push-ebp
    27413     89/<- %ebp 4/r32/esp
    27414     # . save registers
    27415     50/push-eax
    27416     51/push-ecx
    27417     56/push-esi
    27418     57/push-edi
    27419     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
    27420     8b/-> *(ebp+0xc) 0/r32/eax
    27421     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27422     89/<- %esi 0/r32/eax
    27423     # var curr-output/edi: (addr list var) = fn->outputs
    27424     8b/-> *(ebp+0x10) 0/r32/eax
    27425     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    27426     89/<- %edi 0/r32/eax
    27427     {
    27428 $emit-outputs:loop:
    27429       81 7/subop/compare %esi 0/imm32
    27430       0f 84/jump-if-= break/disp32
    27431       # emit copy to output register
    27432       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
    27433       (lookup *edi *(edi+4))  # List-value List-value => eax
    27434       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    27435       89/<- %ecx 0/r32/eax
    27436       # if curr-output-register starts with "x", emit a floating-point copy
    27437       8a/copy-byte *(ecx+4) 0/r32/AL
    27438       81 4/subop/and %eax 0xff/imm32
    27439       3d/compare-eax-and 0x78/imm32/x
    27440       {
    27441         75/jump-if-!= break/disp8
    27442         (emit-float-output *(ebp+8) %esi %ecx)
    27443         eb/jump $emit-outputs:continue/disp8
    27444       }
    27445       # otherwise emit an int copy
    27446       (emit-int-output *(ebp+8) %esi %ecx)
    27447 $emit-outputs:continue:
    27448       # curr-inout = curr-inout->next
    27449       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    27450       89/<- %esi 0/r32/eax
    27451       # curr-output = curr-output->next
    27452       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    27453       89/<- %edi 0/r32/eax
    27454       #
    27455       e9/jump loop/disp32
    27456     }
    27457 $emit-outputs:end:
    27458     # . restore registers
    27459     5f/pop-to-edi
    27460     5e/pop-to-esi
    27461     59/pop-to-ecx
    27462     58/pop-to-eax
    27463     # . epilogue
    27464     89/<- %esp 5/r32/ebp
    27465     5d/pop-to-ebp
    27466     c3/return
    27467
    27468 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27469     # . prologue
    27470     55/push-ebp
    27471     89/<- %ebp 4/r32/esp
    27472     # . save registers
    27473     50/push-eax
    27474     51/push-ecx
    27475     # ecx = return-var->value
    27476     8b/-> *(ebp+0xc) 0/r32/eax
    27477     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27478     89/<- %ecx 0/r32/eax
    27479     # if curr-var is a literal, emit copy of a literal to the output
    27480     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    27481     (simple-mu-type? %eax 0)  # literal => eax
    27482     {
    27483       3d/compare-eax-and 0/imm32/false
    27484       0f 84/jump-if-= break/disp32
    27485       (emit-indent *(ebp+8) *Curr-block-depth)
    27486       (write-buffered *(ebp+8) "c7 0/subop/copy %")
    27487       (write-buffered *(ebp+8) *(ebp+0x10))
    27488       (write-buffered *(ebp+8) " ")
    27489       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    27490       (write-buffered *(ebp+8) %eax)
    27491       (write-buffered *(ebp+8) "/imm32\n")
    27492       e9/jump $emit-int-output:end/disp32
    27493     }
    27494     # otherwise emit an integer copy
    27495     (emit-indent *(ebp+8) *Curr-block-depth)
    27496     (write-buffered *(ebp+8) "8b/->")
    27497     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27498     (write-buffered *(ebp+8) " ")
    27499     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27500     (write-int32-hex-buffered *(ebp+8) *eax)
    27501     (write-buffered *(ebp+8) "/r32\n")
    27502 $emit-int-output:end:
    27503     # . restore registers
    27504     59/pop-to-ecx
    27505     58/pop-to-eax
    27506     # . epilogue
    27507     89/<- %esp 5/r32/ebp
    27508     5d/pop-to-ebp
    27509     c3/return
    27510
    27511 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27512     # . prologue
    27513     55/push-ebp
    27514     89/<- %ebp 4/r32/esp
    27515     # . save registers
    27516     50/push-eax
    27517     #
    27518     (emit-indent *(ebp+8) *Curr-block-depth)
    27519     (write-buffered *(ebp+8) "f3 0f 10/->")
    27520     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27521     (write-buffered *(ebp+8) " ")
    27522     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27523     (write-int32-hex-buffered *(ebp+8) *eax)
    27524     (write-buffered *(ebp+8) "/x32\n")
    27525 $emit-float-output:end:
    27526     # . restore registers
    27527     58/pop-to-eax
    27528     # . epilogue
    27529     89/<- %esp 5/r32/ebp
    27530     5d/pop-to-ebp
    27531     c3/return
    27532
    27533 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
    27534     # . prologue
    27535     55/push-ebp
    27536     89/<- %ebp 4/r32/esp
    27537     # . save registers
    27538     51/push-ecx
    27539     # ecx = lookup(stmt->operation)
    27540     8b/-> *(ebp+8) 1/r32/ecx
    27541     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27542     89/<- %ecx 0/r32/eax
    27543     # if (stmt->operation starts with "loop") return true
    27544     (string-starts-with? %ecx "loop")  # => eax
    27545     3d/compare-eax-and 0/imm32/false
    27546     75/jump-if-not-equal $mu-branch?:end/disp8
    27547     # if (stmt->operation starts with "break") return true
    27548     (string-starts-with? %ecx "break")  # => eax
    27549     3d/compare-eax-and 0/imm32/false
    27550     75/jump-if-not-equal $mu-branch?:end/disp8
    27551     # otherwise return (stmt->operation starts with "return")
    27552     (string-starts-with? %ecx "return")  # => eax
    27553 $mu-branch?:end:
    27554     # . restore registers
    27555     59/pop-to-ecx
    27556     # . epilogue
    27557     89/<- %esp 5/r32/ebp
    27558     5d/pop-to-ebp
    27559     c3/return
    27560
    27561 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
    27562     # . prologue
    27563     55/push-ebp
    27564     89/<- %ebp 4/r32/esp
    27565     # . save registers
    27566     50/push-eax
    27567     # eax = stmt
    27568     8b/-> *(ebp+0xc) 0/r32/eax
    27569     #
    27570     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    27571     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
    27572     (emit-indent *(ebp+8) *Curr-block-depth)
    27573     (lookup *eax *(eax+4))  # => eax
    27574     (write-buffered *(ebp+8) %eax)
    27575     (write-buffered *(ebp+8) " break/disp32\n")
    27576 $emit-reverse-break:end:
    27577     # . restore registers
    27578     58/pop-to-eax
    27579     # . epilogue
    27580     89/<- %esp 5/r32/ebp
    27581     5d/pop-to-ebp
    27582     c3/return
    27583
    27584 == data
    27585
    27586 # Table from Mu branch instructions to the reverse SubX opcodes for them.
    27587 Reverse-branch:  # (table (handle array byte) (handle array byte))
    27588   # a table is a stream
    27589   0x1c0/imm32/write
    27590   0/imm32/read
    27591   0x1c0/imm32/size
    27592   # data
    27593   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27594   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27595   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27596   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27597   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27598   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27599   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27600   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27601   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27602   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27603   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27604   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27605   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27606   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27607   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27608   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27609   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27610   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27611   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27612   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27613   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27614   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27615   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27616   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27617   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27618   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27619   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27620   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27621
    27622 == code
    27623
    27624 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
    27625     # . prologue
    27626     55/push-ebp
    27627     89/<- %ebp 4/r32/esp
    27628     # . save registers
    27629     50/push-eax
    27630     51/push-ecx
    27631     52/push-edx
    27632     53/push-ebx
    27633     56/push-esi
    27634     # ecx = vars
    27635     8b/-> *(ebp+0xc) 1/r32/ecx
    27636     # var eax: int = vars->top
    27637     8b/-> *ecx 0/r32/eax
    27638     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27639     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27640     # var min/ecx: (addr handle var) = vars->data
    27641     8d/copy-address *(ecx+8) 1/r32/ecx
    27642     # edx = depth
    27643     8b/-> *(ebp+0x10) 2/r32/edx
    27644     {
    27645 $emit-unconditional-jump-to-depth:loop:
    27646       # if (curr < min) break
    27647       39/compare %esi 1/r32/ecx
    27648       0f 82/jump-if-addr< break/disp32
    27649       # var v/ebx: (addr var) = lookup(*curr)
    27650       (lookup *esi *(esi+4))  # => eax
    27651       89/<- %ebx 0/r32/eax
    27652       # if (v->block-depth < until-block-depth) break
    27653       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27654       0f 8c/jump-if-< break/disp32
    27655       {
    27656 $emit-unconditional-jump-to-depth:check:
    27657         # if v->block-depth != until-block-depth, continue
    27658         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27659         0f 85/jump-if-!= break/disp32
    27660 $emit-unconditional-jump-to-depth:depth-found:
    27661         # if v is not a literal, continue
    27662         (size-of %ebx)  # => eax
    27663         3d/compare-eax-and 0/imm32
    27664         0f 85/jump-if-!= break/disp32
    27665 $emit-unconditional-jump-to-depth:label-found:
    27666         # emit unconditional jump, then return
    27667         (emit-indent *(ebp+8) *Curr-block-depth)
    27668         (write-buffered *(ebp+8) "e9/jump ")
    27669         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    27670         (write-buffered *(ebp+8) %eax)
    27671         (write-buffered *(ebp+8) ":")
    27672         (write-buffered *(ebp+8) *(ebp+0x14))
    27673         (write-buffered *(ebp+8) "/disp32\n")
    27674         eb/jump $emit-unconditional-jump-to-depth:end/disp8
    27675       }
    27676       # curr -= 12
    27677       81 5/subop/subtract %esi 0xc/imm32
    27678       e9/jump loop/disp32
    27679     }
    27680     # TODO: error if no label at 'depth' was found
    27681 $emit-unconditional-jump-to-depth:end:
    27682     # . restore registers
    27683     5e/pop-to-esi
    27684     5b/pop-to-ebx
    27685     5a/pop-to-edx
    27686     59/pop-to-ecx
    27687     58/pop-to-eax
    27688     # . epilogue
    27689     89/<- %esp 5/r32/ebp
    27690     5d/pop-to-ebp
    27691     c3/return
    27692
    27693 # emit clean-up code for 'vars' until some block depth
    27694 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27695 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
    27696     # . prologue
    27697     55/push-ebp
    27698     89/<- %ebp 4/r32/esp
    27699     # . save registers
    27700     50/push-eax
    27701     51/push-ecx
    27702     52/push-edx
    27703     53/push-ebx
    27704     56/push-esi
    27705 #?     (write-buffered Stderr "--- cleanup\n")
    27706 #?     (flush Stderr)
    27707     # ecx = vars
    27708     8b/-> *(ebp+0xc) 1/r32/ecx
    27709     # var esi: int = vars->top
    27710     8b/-> *ecx 6/r32/esi
    27711     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27712     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27713     # var min/ecx: (addr handle var) = vars->data
    27714     81 0/subop/add %ecx 8/imm32
    27715     # edx = until-block-depth
    27716     8b/-> *(ebp+0x10) 2/r32/edx
    27717     {
    27718 $emit-cleanup-code-until-depth:loop:
    27719       # if (curr < min) break
    27720       39/compare %esi 1/r32/ecx
    27721       0f 82/jump-if-addr< break/disp32
    27722       # var v/ebx: (addr var) = lookup(*curr)
    27723       (lookup *esi *(esi+4))  # => eax
    27724       89/<- %ebx 0/r32/eax
    27725 #?       (lookup *ebx *(ebx+4))  # Var-name
    27726 #?       (write-buffered Stderr "var ")
    27727 #?       (write-buffered Stderr %eax)
    27728 #?       (write-buffered Stderr Newline)
    27729 #?       (flush Stderr)
    27730       # if (v->block-depth < until-block-depth) break
    27731       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27732       0f 8c/jump-if-< break/disp32
    27733       # if v is in a register
    27734       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27735       {
    27736         0f 84/jump-if-= break/disp32
    27737         {
    27738 $emit-cleanup-code-until-depth:check-for-previous-spill:
    27739           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27740           3d/compare-eax-and 0/imm32/false
    27741           74/jump-if-= break/disp8
    27742 $emit-cleanup-code-until-depth:reclaim-var-in-register:
    27743           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27744           (emit-pop-register *(ebp+8) %eax)
    27745         }
    27746         eb/jump $emit-cleanup-code-until-depth:continue/disp8
    27747       }
    27748       # otherwise v is on the stack
    27749       {
    27750         75/jump-if-!= break/disp8
    27751 $emit-cleanup-code-until-depth:var-on-stack:
    27752         (size-of %ebx)  # => eax
    27753         # don't emit code for labels
    27754         3d/compare-eax-and 0/imm32
    27755         74/jump-if-= break/disp8
    27756 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
    27757         (emit-indent *(ebp+8) *Curr-block-depth)
    27758         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27759         (write-int32-hex-buffered *(ebp+8) %eax)
    27760         (write-buffered *(ebp+8) "/imm32\n")
    27761       }
    27762 $emit-cleanup-code-until-depth:continue:
    27763       # curr -= 12
    27764       81 5/subop/subtract %esi 0xc/imm32
    27765       e9/jump loop/disp32
    27766     }
    27767 $emit-cleanup-code-until-depth:end:
    27768     # . restore registers
    27769     5e/pop-to-esi
    27770     5b/pop-to-ebx
    27771     5a/pop-to-edx
    27772     59/pop-to-ecx
    27773     58/pop-to-eax
    27774     # . epilogue
    27775     89/<- %esp 5/r32/ebp
    27776     5d/pop-to-ebp
    27777     c3/return
    27778
    27779 # emit clean-up code for 'vars' that don't conflict with output registers
    27780 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27781 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
    27782     # . prologue
    27783     55/push-ebp
    27784     89/<- %ebp 4/r32/esp
    27785     # . save registers
    27786     50/push-eax
    27787     51/push-ecx
    27788     52/push-edx
    27789     53/push-ebx
    27790     56/push-esi
    27791     57/push-edi
    27792     # ecx = vars
    27793     8b/-> *(ebp+0xc) 1/r32/ecx
    27794     # var esi: int = vars->top
    27795     8b/-> *ecx 6/r32/esi
    27796     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27797     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27798     # var min/ecx: (addr handle var) = vars->data
    27799     81 0/subop/add %ecx 8/imm32
    27800     {
    27801 $emit-cleanup-code-for-non-outputs:loop:
    27802       # if (curr < min) break
    27803       39/compare %esi 1/r32/ecx
    27804       0f 82/jump-if-addr< break/disp32
    27805       # var v/ebx: (addr var) = lookup(*curr)
    27806       (lookup *esi *(esi+4))  # => eax
    27807       89/<- %ebx 0/r32/eax
    27808       # if v is in a register
    27809       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27810       {
    27811         0f 84/jump-if-= break/disp32
    27812         {
    27813 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
    27814           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27815           3d/compare-eax-and 0/imm32/false
    27816           0f 84/jump-if-= break/disp32
    27817 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
    27818           # var reg/edi: (addr array name) = v->register
    27819           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27820           89/<- %edi 0/r32/eax
    27821           # if reg is not in function outputs, emit a pop
    27822           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
    27823           3d/compare-eax-and 0/imm32/false
    27824           {
    27825             75/jump-if-!= break/disp8
    27826             (emit-pop-register *(ebp+8) %edi)
    27827             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
    27828           }
    27829           # otherwise just drop it from the stack
    27830           (emit-indent *(ebp+8) *Curr-block-depth)
    27831           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27832         }
    27833 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
    27834         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
    27835       }
    27836       # otherwise v is on the stack
    27837       {
    27838         75/jump-if-!= break/disp8
    27839 $emit-cleanup-code-for-non-outputs:var-on-stack:
    27840         (size-of %ebx)  # => eax
    27841         # don't emit code for labels
    27842         3d/compare-eax-and 0/imm32
    27843         74/jump-if-= break/disp8
    27844 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
    27845         (emit-indent *(ebp+8) *Curr-block-depth)
    27846         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27847         (write-int32-hex-buffered *(ebp+8) %eax)
    27848         (write-buffered *(ebp+8) "/imm32\n")
    27849       }
    27850 $emit-cleanup-code-for-non-outputs:continue:
    27851       # curr -= 12
    27852       81 5/subop/subtract %esi 0xc/imm32
    27853       e9/jump loop/disp32
    27854     }
    27855 $emit-cleanup-code-for-non-outputs:end:
    27856     # . restore registers
    27857     5f/pop-to-edi
    27858     5e/pop-to-esi
    27859     5b/pop-to-ebx
    27860     5a/pop-to-edx
    27861     59/pop-to-ecx
    27862     58/pop-to-eax
    27863     # . epilogue
    27864     89/<- %esp 5/r32/ebp
    27865     5d/pop-to-ebp
    27866     c3/return
    27867
    27868 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
    27869     # . prologue
    27870     55/push-ebp
    27871     89/<- %ebp 4/r32/esp
    27872     # eax = reg
    27873     8b/-> *(ebp+0xc) 0/r32/eax
    27874     # var prefix/eax: byte = reg->data[0]
    27875     8a/copy-byte *(eax+4) 0/r32/AL
    27876     81 4/subop/and %eax 0xff/imm32
    27877     # if (prefix == 'x') push xmm register
    27878     {
    27879       3d/compare-eax-and 0x78/imm32/x
    27880       0f 85/jump-if-!= break/disp32
    27881       # TODO validate register
    27882       (emit-indent *(ebp+8) *Curr-block-depth)
    27883       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
    27884       (emit-indent *(ebp+8) *Curr-block-depth)
    27885       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
    27886       # var prefix/eax: byte = reg->data[3]
    27887       8b/-> *(ebp+0xc) 0/r32/eax
    27888       8a/copy-byte *(eax+7) 0/r32/AL
    27889       81 4/subop/and %eax 0xff/imm32
    27890       (write-byte-buffered *(ebp+8) %eax)
    27891       (write-buffered *(ebp+8) "/x32\n")
    27892       e9/jump $emit-push-register:end/disp32
    27893     }
    27894     # otherwise push gp register
    27895     (emit-indent *(ebp+8) *Curr-block-depth)
    27896     (write-buffered *(ebp+8) "ff 6/subop/push %")
    27897     (write-buffered *(ebp+8) *(ebp+0xc))
    27898     (write-buffered *(ebp+8) Newline)
    27899 $emit-push-register:end:
    27900     # . epilogue
    27901     89/<- %esp 5/r32/ebp
    27902     5d/pop-to-ebp
    27903     c3/return
    27904
    27905 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
    27906     # . prologue
    27907     55/push-ebp
    27908     89/<- %ebp 4/r32/esp
    27909     # . save registers
    27910     50/push-eax
    27911     # eax = reg
    27912     8b/-> *(ebp+0xc) 0/r32/eax
    27913     # var prefix/eax: byte = reg->data[0]
    27914     8a/copy-byte *(eax+4) 0/r32/AL
    27915     81 4/subop/and %eax 0xff/imm32
    27916     # if (prefix == 'x') pop to xmm register
    27917     {
    27918       3d/compare-eax-and 0x78/imm32/x
    27919       0f 85/jump-if-!= break/disp32
    27920       # TODO validate register
    27921       (emit-indent *(ebp+8) *Curr-block-depth)
    27922       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
    27923       # var prefix/eax: byte = reg->data[3]
    27924       8b/-> *(ebp+0xc) 0/r32/eax
    27925       8a/copy-byte *(eax+7) 0/r32/AL
    27926       81 4/subop/and %eax 0xff/imm32
    27927       (write-byte-buffered *(ebp+8) %eax)
    27928       (write-buffered *(ebp+8) "/x32\n")
    27929       (emit-indent *(ebp+8) *Curr-block-depth)
    27930       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27931       e9/jump $emit-pop-register:end/disp32
    27932     }
    27933     # otherwise pop to gp register
    27934     (emit-indent *(ebp+8) *Curr-block-depth)
    27935     (write-buffered *(ebp+8) "8f 0/subop/pop %")
    27936     (write-buffered *(ebp+8) *(ebp+0xc))
    27937     (write-buffered *(ebp+8) Newline)
    27938 $emit-pop-register:end:
    27939     # . restore registers
    27940     58/pop-to-eax
    27941     # . epilogue
    27942     89/<- %esp 5/r32/ebp
    27943     5d/pop-to-ebp
    27944     c3/return
    27945
    27946 # emit clean-up code for 'vars' until a given label is encountered
    27947 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27948 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
    27949     # . prologue
    27950     55/push-ebp
    27951     89/<- %ebp 4/r32/esp
    27952     # . save registers
    27953     50/push-eax
    27954     51/push-ecx
    27955     52/push-edx
    27956     53/push-ebx
    27957     # ecx = vars
    27958     8b/-> *(ebp+0xc) 1/r32/ecx
    27959     # var eax: int = vars->top
    27960     8b/-> *ecx 0/r32/eax
    27961     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    27962     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    27963     # var min/ecx: (addr handle var) = vars->data
    27964     81 0/subop/add %ecx 8/imm32
    27965     {
    27966 $emit-cleanup-code-until-target:loop:
    27967       # if (curr < min) break
    27968       39/compare %edx 1/r32/ecx
    27969       0f 82/jump-if-addr< break/disp32
    27970       # var v/ebx: (handle var) = lookup(*curr)
    27971       (lookup *edx *(edx+4))  # => eax
    27972       89/<- %ebx 0/r32/eax
    27973       # if (v->name == until-block-label) break
    27974       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    27975       (string-equal? %eax *(ebp+0x10))  # => eax
    27976       3d/compare-eax-and 0/imm32/false
    27977       0f 85/jump-if-!= break/disp32
    27978       # if v is in a register
    27979       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27980       {
    27981         0f 84/jump-if-= break/disp32
    27982         {
    27983 $emit-cleanup-code-until-target:check-for-previous-spill:
    27984           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
    27985           3d/compare-eax-and 0/imm32/false
    27986           74/jump-if-= break/disp8
    27987 $emit-cleanup-code-until-target:reclaim-var-in-register:
    27988           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27989           (emit-pop-register *(ebp+8) %eax)
    27990         }
    27991         eb/jump $emit-cleanup-code-until-target:continue/disp8
    27992       }
    27993       # otherwise v is on the stack
    27994       {
    27995         75/jump-if-!= break/disp8
    27996 $emit-cleanup-code-until-target:reclaim-var-on-stack:
    27997         (size-of %ebx)  # => eax
    27998         # don't emit code for labels
    27999         3d/compare-eax-and 0/imm32
    28000         74/jump-if-= break/disp8
    28001         #
    28002         (emit-indent *(ebp+8) *Curr-block-depth)
    28003         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    28004         (write-int32-hex-buffered *(ebp+8) %eax)
    28005         (write-buffered *(ebp+8) "/imm32\n")
    28006       }
    28007 $emit-cleanup-code-until-target:continue:
    28008       # curr -= 12
    28009       81 5/subop/subtract %edx 0xc/imm32
    28010       e9/jump loop/disp32
    28011     }
    28012 $emit-cleanup-code-until-target:end:
    28013     # . restore registers
    28014     5b/pop-to-ebx
    28015     5a/pop-to-edx
    28016     59/pop-to-ecx
    28017     58/pop-to-eax
    28018     # . epilogue
    28019     89/<- %esp 5/r32/ebp
    28020     5d/pop-to-ebp
    28021     c3/return
    28022
    28023 # update Curr-local-stack-offset assuming vars until some block depth are popped
    28024 # doesn't actually modify 'vars', so we need traverse manually inside the stack
    28025 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
    28026     # . prologue
    28027     55/push-ebp
    28028     89/<- %ebp 4/r32/esp
    28029     # . save registers
    28030     50/push-eax
    28031     51/push-ecx
    28032     52/push-edx
    28033     53/push-ebx
    28034     56/push-esi
    28035     # ecx = vars
    28036     8b/-> *(ebp+8) 1/r32/ecx
    28037     # var esi: int = vars->top
    28038     8b/-> *ecx 6/r32/esi
    28039     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    28040     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    28041     # var min/ecx: (addr handle var) = vars->data
    28042     81 0/subop/add %ecx 8/imm32
    28043     # edx = until-block-depth
    28044     8b/-> *(ebp+0xc) 2/r32/edx
    28045     {
    28046 $clean-up-stack-offset-state:loop:
    28047       # if (curr < min) break
    28048       39/compare %esi 1/r32/ecx
    28049       0f 82/jump-if-addr< break/disp32
    28050       # var v/ebx: (addr var) = lookup(*curr)
    28051       (lookup *esi *(esi+4))  # => eax
    28052       89/<- %ebx 0/r32/eax
    28053       # if (v->block-depth < until-block-depth) break
    28054       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    28055       0f 8c/jump-if-< break/disp32
    28056       # if v is in a register
    28057       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    28058       {
    28059         0f 84/jump-if-= break/disp32
    28060         {
    28061 $clean-up-stack-offset-state:check-for-previous-spill:
    28062           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    28063           3d/compare-eax-and 0/imm32/false
    28064           74/jump-if-= break/disp8
    28065 $clean-up-stack-offset-state:reclaim-var-in-register:
    28066           81 0/subop/add *Curr-local-stack-offset 4/imm32
    28067         }
    28068         eb/jump $clean-up-stack-offset-state:continue/disp8
    28069       }
    28070       # otherwise v is on the stack
    28071       {
    28072         75/jump-if-!= break/disp8
    28073 $clean-up-stack-offset-state:var-on-stack:
    28074         (size-of %ebx)  # => eax
    28075         01/add-to *Curr-local-stack-offset 0/r32/eax
    28076       }
    28077 $clean-up-stack-offset-state:continue:
    28078       # curr -= 12
    28079       81 5/subop/subtract %esi 0xc/imm32
    28080       e9/jump loop/disp32
    28081     }
    28082 $clean-up-stack-offset-state:end:
    28083     # . restore registers
    28084     5e/pop-to-esi
    28085     5b/pop-to-ebx
    28086     5a/pop-to-edx
    28087     59/pop-to-ecx
    28088     58/pop-to-eax
    28089     # . epilogue
    28090     89/<- %esp 5/r32/ebp
    28091     5d/pop-to-ebp
    28092     c3/return
    28093
    28094 # Return true if there isn't a variable in 'vars' with the same block-depth
    28095 # and register as 'v'.
    28096 # 'v' is guaranteed not to be within 'vars'.
    28097 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    28098     # . prologue
    28099     55/push-ebp
    28100     89/<- %ebp 4/r32/esp
    28101     # . save registers
    28102     51/push-ecx
    28103     52/push-edx
    28104     53/push-ebx
    28105     56/push-esi
    28106     57/push-edi
    28107     # ecx = vars
    28108     8b/-> *(ebp+0xc) 1/r32/ecx
    28109     # var eax: int = vars->top
    28110     8b/-> *ecx 0/r32/eax
    28111     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    28112     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    28113     # var min/ecx: (addr handle var) = vars->data
    28114     8d/copy-address *(ecx+8) 1/r32/ecx
    28115     # var depth/ebx: int = v->block-depth
    28116     8b/-> *(ebp+8) 3/r32/ebx
    28117     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
    28118     # var needle/esi: (addr array byte) = v->register
    28119     8b/-> *(ebp+8) 6/r32/esi
    28120     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    28121     89/<- %esi 0/r32/eax
    28122     {
    28123 $not-yet-spilled-this-block?:loop:
    28124       # if (curr < min) break
    28125       39/compare %edx 1/r32/ecx
    28126       0f 82/jump-if-addr< break/disp32
    28127       # var cand/edi: (addr var) = lookup(*curr)
    28128       (lookup *edx *(edx+4))  # => eax
    28129       89/<- %edi 0/r32/eax
    28130       # if (cand->block-depth < depth) break
    28131       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
    28132       0f 8c/jump-if-< break/disp32
    28133       # var cand-reg/edi: (array array byte) = cand->reg
    28134       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    28135       89/<- %edi 0/r32/eax
    28136       # if (cand-reg == null) continue
    28137       {
    28138 $not-yet-spilled-this-block?:check-reg:
    28139         81 7/subop/compare %edi 0/imm32
    28140         0f 84/jump-if-= break/disp32
    28141         # if (cand-reg == needle) return true
    28142         (string-equal? %esi %edi)  # => eax
    28143         3d/compare-eax-and 0/imm32/false
    28144         74/jump-if-= break/disp8
    28145 $not-yet-spilled-this-block?:return-false:
    28146         b8/copy-to-eax 0/imm32/false
    28147         eb/jump $not-yet-spilled-this-block?:end/disp8
    28148       }
    28149 $not-yet-spilled-this-block?:continue:
    28150       # curr -= 12
    28151       81 5/subop/subtract %edx 0xc/imm32
    28152       e9/jump loop/disp32
    28153     }
    28154 $not-yet-spilled-this-block?:return-true:
    28155     # return true
    28156     b8/copy-to-eax 1/imm32/true
    28157 $not-yet-spilled-this-block?:end:
    28158     # . restore registers
    28159     5f/pop-to-edi
    28160     5e/pop-to-esi
    28161     5b/pop-to-ebx
    28162     5a/pop-to-edx
    28163     59/pop-to-ecx
    28164     # . epilogue
    28165     89/<- %esp 5/r32/ebp
    28166     5d/pop-to-ebp
    28167     c3/return
    28168
    28169 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
    28170 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
    28171     # . prologue
    28172     55/push-ebp
    28173     89/<- %ebp 4/r32/esp
    28174     # eax = v
    28175     8b/-> *(ebp+8) 0/r32/eax
    28176     # var reg/eax: (addr array byte) = lookup(v->register)
    28177     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28178     # var target/eax: (addr var) = find-register(fn-outputs, reg)
    28179     (find-register *(ebp+0x10) %eax)  # => eax
    28180     # if (target == 0) return true
    28181     {
    28182       3d/compare-eax-and 0/imm32
    28183       75/jump-if-!= break/disp8
    28184       b8/copy-to-eax 1/imm32/true
    28185       eb/jump $will-not-write-some-register?:end/disp8
    28186     }
    28187     # return !assigns-in-stmts?(stmts, target)
    28188     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
    28189     3d/compare-eax-and 0/imm32/false
    28190     # assume: true = 1, so no need to mask with 0x000000ff
    28191     0f 94/set-if-= %al
    28192 $will-not-write-some-register?:end:
    28193     # . epilogue
    28194     89/<- %esp 5/r32/ebp
    28195     5d/pop-to-ebp
    28196     c3/return
    28197
    28198 # return fn output with matching register
    28199 # always returns false if 'reg' is null
    28200 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
    28201     # . prologue
    28202     55/push-ebp
    28203     89/<- %ebp 4/r32/esp
    28204     # . save registers
    28205     51/push-ecx
    28206     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28207     8b/-> *(ebp+8) 1/r32/ecx
    28208     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    28209     89/<- %ecx 0/r32/eax
    28210     {
    28211 $find-register:loop:
    28212       # if (curr == 0) break
    28213       81 7/subop/compare %ecx 0/imm32
    28214       74/jump-if-= break/disp8
    28215       # eax = curr->value->register
    28216       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28217       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28218       # if (eax == reg) return curr->value
    28219 $find-register:compare:
    28220       (string-equal? *(ebp+0xc) %eax)  # => eax
    28221       {
    28222         3d/compare-eax-and 0/imm32/false
    28223         74/jump-if-= break/disp8
    28224 $find-register:found:
    28225         (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28226         eb/jump $find-register:end/disp8
    28227       }
    28228       # curr = lookup(curr->next)
    28229       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28230       89/<- %ecx 0/r32/eax
    28231       #
    28232       eb/jump loop/disp8
    28233     }
    28234 $find-register:end:
    28235     # . restore registers
    28236     59/pop-to-ecx
    28237     # . epilogue
    28238     89/<- %esp 5/r32/ebp
    28239     5d/pop-to-ebp
    28240     c3/return
    28241
    28242 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
    28243     # . prologue
    28244     55/push-ebp
    28245     89/<- %ebp 4/r32/esp
    28246     # . save registers
    28247     51/push-ecx
    28248     # var curr/ecx: (addr list stmt) = stmts
    28249     8b/-> *(ebp+8) 1/r32/ecx
    28250     {
    28251       # if (curr == 0) break
    28252       81 7/subop/compare %ecx 0/imm32
    28253       74/jump-if-= break/disp8
    28254       # if assigns-in-stmt?(curr->value, v) return true
    28255       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28256       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
    28257       3d/compare-eax-and 0/imm32/false
    28258       75/jump-if-!= break/disp8
    28259       # curr = lookup(curr->next)
    28260       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28261       89/<- %ecx 0/r32/eax
    28262       #
    28263       eb/jump loop/disp8
    28264     }
    28265 $assigns-in-stmts?:end:
    28266     # . restore registers
    28267     59/pop-to-ecx
    28268     # . epilogue
    28269     89/<- %esp 5/r32/ebp
    28270     5d/pop-to-ebp
    28271     c3/return
    28272
    28273 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
    28274     # . prologue
    28275     55/push-ebp
    28276     89/<- %ebp 4/r32/esp
    28277     # . save registers
    28278     51/push-ecx
    28279     # ecx = stmt
    28280     8b/-> *(ebp+8) 1/r32/ecx
    28281     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
    28282     {
    28283       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    28284       75/jump-if-!= break/disp8
    28285       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28286       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
    28287       eb/jump $assigns-in-stmt?:end/disp8
    28288     }
    28289     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
    28290     {
    28291       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    28292       75/jump-if-!= break/disp8
    28293       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
    28294       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
    28295       eb/jump $assigns-in-stmt?:end/disp8
    28296     }
    28297     # otherwise return false
    28298     b8/copy 0/imm32/false
    28299 $assigns-in-stmt?:end:
    28300     # . restore registers
    28301     59/pop-to-ecx
    28302     # . epilogue
    28303     89/<- %esp 5/r32/ebp
    28304     5d/pop-to-ebp
    28305     c3/return
    28306
    28307 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
    28308     # . prologue
    28309     55/push-ebp
    28310     89/<- %ebp 4/r32/esp
    28311     # . save registers
    28312     51/push-ecx
    28313     # var curr/ecx: (addr stmt-var) = stmt-var
    28314     8b/-> *(ebp+8) 1/r32/ecx
    28315     {
    28316       # if (curr == 0) break
    28317       81 7/subop/compare %ecx 0/imm32
    28318       74/jump-if-= break/disp8
    28319       # eax = lookup(curr->value)
    28320       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    28321       # if (eax == v  &&  curr->is-deref? == false) return true
    28322       {
    28323         39/compare *(ebp+0xc) 0/r32/eax
    28324         75/jump-if-!= break/disp8
    28325         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    28326         75/jump-if-!= break/disp8
    28327         b8/copy-to-eax 1/imm32/true
    28328         eb/jump $assigns-in-stmt-vars?:end/disp8
    28329       }
    28330       # curr = lookup(curr->next)
    28331       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    28332       89/<- %ecx 0/r32/eax
    28333       #
    28334       eb/jump loop/disp8
    28335     }
    28336 $assigns-in-stmt-vars?:end:
    28337     # . restore registers
    28338     59/pop-to-ecx
    28339     # . epilogue
    28340     89/<- %esp 5/r32/ebp
    28341     5d/pop-to-ebp
    28342     c3/return
    28343
    28344 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
    28345 # v is guaranteed to be within vars
    28346 # 'start' is provided as an optimization, a pointer within vars
    28347 # *start == v
    28348 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
    28349     # . prologue
    28350     55/push-ebp
    28351     89/<- %ebp 4/r32/esp
    28352     # . save registers
    28353     51/push-ecx
    28354     52/push-edx
    28355     53/push-ebx
    28356     56/push-esi
    28357     57/push-edi
    28358     # ecx = v
    28359     8b/-> *(ebp+8) 1/r32/ecx
    28360     # var reg/edx: (addr array byte) = lookup(v->register)
    28361     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    28362     89/<- %edx 0/r32/eax
    28363     # var depth/ebx: int = v->block-depth
    28364     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
    28365     # var min/ecx: (addr handle var) = vars->data
    28366     8b/-> *(ebp+0xc) 1/r32/ecx
    28367     81 0/subop/add %ecx 8/imm32
    28368     # TODO: check that start >= min and start < &vars->data[top]
    28369     # TODO: check that *start == v
    28370     # var curr/esi: (addr handle var) = start
    28371     8b/-> *(ebp+0x10) 6/r32/esi
    28372     # curr -= 8
    28373     81 5/subop/subtract %esi 8/imm32
    28374     {
    28375 $same-register-spilled-before?:loop:
    28376       # if (curr < min) break
    28377       39/compare %esi 1/r32/ecx
    28378       0f 82/jump-if-addr< break/disp32
    28379       # var x/eax: (addr var) = lookup(*curr)
    28380       (lookup *esi *(esi+4))  # => eax
    28381       # if (x->block-depth < depth) break
    28382       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
    28383       0f 8c/jump-if-< break/disp32
    28384       # if (x->register == 0) continue
    28385       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    28386       74/jump-if-= $same-register-spilled-before?:continue/disp8
    28387       # if (x->register == reg) return true
    28388       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28389       (string-equal? %eax %edx)  # => eax
    28390       3d/compare-eax-and 0/imm32/false
    28391       b8/copy-to-eax 1/imm32/true
    28392       75/jump-if-!= $same-register-spilled-before?:end/disp8
    28393 $same-register-spilled-before?:continue:
    28394       # curr -= 8
    28395       81 5/subop/subtract %esi 8/imm32
    28396       e9/jump loop/disp32
    28397     }
    28398 $same-register-spilled-before?:false:
    28399     b8/copy-to-eax 0/imm32/false
    28400 $same-register-spilled-before?:end:
    28401     # . restore registers
    28402     5f/pop-to-edi
    28403     5e/pop-to-esi
    28404     5b/pop-to-ebx
    28405     5a/pop-to-edx
    28406     59/pop-to-ecx
    28407     # . epilogue
    28408     89/<- %esp 5/r32/ebp
    28409     5d/pop-to-ebp
    28410     c3/return
    28411
    28412 # clean up global state for 'vars' until some block depth (inclusive)
    28413 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
    28414     # . prologue
    28415     55/push-ebp
    28416     89/<- %ebp 4/r32/esp
    28417     # . save registers
    28418     50/push-eax
    28419     51/push-ecx
    28420     56/push-esi
    28421     # esi = vars
    28422     8b/-> *(ebp+8) 6/r32/esi
    28423     # ecx = until-block-depth
    28424     8b/-> *(ebp+0xc) 1/r32/ecx
    28425     {
    28426 $clean-up-blocks:reclaim-loop:
    28427       # if (vars->top <= 0) break
    28428       8b/-> *esi 0/r32/eax  # Stack-top
    28429       3d/compare-eax-and 0/imm32
    28430       0f 8e/jump-if-<= break/disp32
    28431       # var v/eax: (addr var) = lookup(vars[vars->top-12])
    28432       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
    28433       # if (v->block-depth < until-block-depth) break
    28434       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
    28435       0f 8c/jump-if-< break/disp32
    28436       (pop %esi)  # => eax
    28437       (pop %esi)  # => eax
    28438       (pop %esi)  # => eax
    28439       e9/jump loop/disp32
    28440     }
    28441 $clean-up-blocks:end:
    28442     # . restore registers
    28443     5e/pop-to-esi
    28444     59/pop-to-ecx
    28445     58/pop-to-eax
    28446     # . epilogue
    28447     89/<- %esp 5/r32/ebp
    28448     5d/pop-to-ebp
    28449     c3/return
    28450
    28451 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
    28452     # . prologue
    28453     55/push-ebp
    28454     89/<- %ebp 4/r32/esp
    28455     # . save registers
    28456     51/push-ecx
    28457     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28458     8b/-> *(ebp+8) 0/r32/eax
    28459     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    28460     89/<- %ecx 0/r32/eax
    28461     # while curr != null
    28462     {
    28463       81 7/subop/compare %ecx 0/imm32
    28464       74/jump-if-= break/disp8
    28465       # var v/eax: (addr var) = lookup(curr->value)
    28466       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28467       # var reg/eax: (addr array byte) = lookup(v->register)
    28468       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28469       # if (reg == target) return true
    28470       (string-equal? %eax *(ebp+0xc))  # => eax
    28471       3d/compare-eax-and 0/imm32/false
    28472       75/jump-if-!= $reg-in-function-outputs?:end/disp8
    28473       # curr = curr->next
    28474       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28475       89/<- %ecx 0/r32/eax
    28476       #
    28477       eb/jump loop/disp8
    28478     }
    28479     # return false
    28480     b8/copy-to-eax 0/imm32
    28481 $reg-in-function-outputs?:end:
    28482     # . restore registers
    28483     59/pop-to-ecx
    28484     # . epilogue
    28485     89/<- %esp 5/r32/ebp
    28486     5d/pop-to-ebp
    28487     c3/return
    28488
    28489 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
    28490     # . prologue
    28491     55/push-ebp
    28492     89/<- %ebp 4/r32/esp
    28493     # . save registers
    28494     50/push-eax
    28495     51/push-ecx
    28496     52/push-edx
    28497     # eax = stmt
    28498     8b/-> *(ebp+0xc) 0/r32/eax
    28499     # var v/ecx: (addr var)
    28500     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
    28501     89/<- %ecx 0/r32/eax
    28502     # v->block-depth = *Curr-block-depth
    28503     8b/-> *Curr-block-depth 0/r32/eax
    28504     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    28505     # var n/edx: int = size-of(stmt->var)
    28506     (size-of %ecx)  # => eax
    28507     89/<- %edx 0/r32/eax
    28508     # *Curr-local-stack-offset -= n
    28509     29/subtract-from *Curr-local-stack-offset 2/r32/edx
    28510     # v->offset = *Curr-local-stack-offset
    28511     8b/-> *Curr-local-stack-offset 0/r32/eax
    28512     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
    28513     # if v is an array, do something special to initialize it
    28514     {
    28515       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28516       (mu-array? %eax)  # => eax
    28517       3d/compare-eax-and 0/imm32/false
    28518       0f 84/jump-if-= break/disp32
    28519       # var array-size-without-size/edx: int = n-4
    28520       81 5/subop/subtract %edx 4/imm32
    28521       #
    28522       (emit-array-data-initialization *(ebp+8) %edx)
    28523       e9/jump $emit-subx-var-def:end/disp32
    28524     }
    28525     # another special-case for initializing streams
    28526     # a stream is an array with 2 extra pointers
    28527     {
    28528       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28529       (mu-stream? %eax)  # => eax
    28530       3d/compare-eax-and 0/imm32/false
    28531       0f 84/jump-if-= break/disp32
    28532       # var array-size-without-size/edx: int = n-12
    28533       81 5/subop/subtract %edx 0xc/imm32
    28534       (emit-array-data-initialization *(ebp+8) %edx)
    28535       # emit read and write pointers
    28536       (emit-indent *(ebp+8) *Curr-block-depth)
    28537       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28538       (emit-indent *(ebp+8) *Curr-block-depth)
    28539       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28540       #
    28541       eb/jump $emit-subx-var-def:end/disp8
    28542     }
    28543     # while n > 0
    28544     {
    28545       81 7/subop/compare %edx 0/imm32
    28546       7e/jump-if-<= break/disp8
    28547       (emit-indent *(ebp+8) *Curr-block-depth)
    28548       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28549       # n -= 4
    28550       81 5/subop/subtract %edx 4/imm32
    28551       #
    28552       eb/jump loop/disp8
    28553     }
    28554 $emit-subx-var-def:end:
    28555     # . restore registers
    28556     5a/pop-to-edx
    28557     59/pop-to-ecx
    28558     58/pop-to-eax
    28559     # . epilogue
    28560     89/<- %esp 5/r32/ebp
    28561     5d/pop-to-ebp
    28562     c3/return
    28563
    28564 emit-array-data-initialization:  # out: (addr buffered-file), n: int
    28565     # . prologue
    28566     55/push-ebp
    28567     89/<- %ebp 4/r32/esp
    28568     #
    28569     (emit-indent *(ebp+8) *Curr-block-depth)
    28570     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28571     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28572     (write-buffered *(ebp+8) ")\n")
    28573     (emit-indent *(ebp+8) *Curr-block-depth)
    28574     (write-buffered *(ebp+8) "68/push ")
    28575     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28576     (write-buffered *(ebp+8) "/imm32\n")
    28577 $emit-array-data-initialization:end:
    28578     # . epilogue
    28579     89/<- %esp 5/r32/ebp
    28580     5d/pop-to-ebp
    28581     c3/return
    28582
    28583 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    28584     # . prologue
    28585     55/push-ebp
    28586     89/<- %ebp 4/r32/esp
    28587     # . save registers
    28588     50/push-eax
    28589     51/push-ecx
    28590     # - some special-case primitives that don't actually use the 'primitives' data structure
    28591     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    28592     8b/-> *(ebp+0xc) 1/r32/ecx
    28593     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    28594     89/<- %ecx 0/r32/eax
    28595     # copy byte (can be a primitive except we need to emit a second instruction)
    28596     {
    28597       # if (!string-equal?(stmt->operation, "copy-byte")) break
    28598       (string-equal? %ecx "copy-byte")  # => eax
    28599       3d/compare-eax-and 0/imm32/false
    28600       0f 84/jump-if-= break/disp32
    28601       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28602       e9/jump $emit-subx-stmt:end/disp32
    28603     }
    28604     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
    28605     # array size
    28606     {
    28607       # if (!string-equal?(stmt->operation, "length")) break
    28608       (string-equal? %ecx "length")  # => eax
    28609       3d/compare-eax-and 0/imm32/false
    28610       0f 84/jump-if-= break/disp32
    28611       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28612       e9/jump $emit-subx-stmt:end/disp32
    28613     }
    28614     # index into array
    28615     {
    28616       # if (!string-equal?(stmt->operation, "index")) break
    28617       (string-equal? %ecx "index")  # => eax
    28618       3d/compare-eax-and 0/imm32/false
    28619       0f 84/jump-if-= break/disp32
    28620       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    28621       e9/jump $emit-subx-stmt:end/disp32
    28622     }
    28623     # compute-offset for index into array
    28624     {
    28625       # if (!string-equal?(stmt->operation, "compute-offset")) break
    28626       (string-equal? %ecx "compute-offset")  # => eax
    28627       3d/compare-eax-and 0/imm32/false
    28628       0f 84/jump-if-= break/disp32
    28629       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28630       e9/jump $emit-subx-stmt:end/disp32
    28631     }
    28632     # get field from record
    28633     {
    28634       # if (!string-equal?(stmt->operation, "get")) break
    28635       (string-equal? %ecx "get")  # => eax
    28636       3d/compare-eax-and 0/imm32/false
    28637       0f 84/jump-if-= break/disp32
    28638       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
    28639       e9/jump $emit-subx-stmt:end/disp32
    28640     }
    28641     # allocate scalar
    28642     {
    28643       # if (!string-equal?(stmt->operation, "allocate")) break
    28644       (string-equal? %ecx "allocate")  # => eax
    28645       3d/compare-eax-and 0/imm32/false
    28646       0f 84/jump-if-= break/disp32
    28647       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28648       e9/jump $emit-subx-stmt:end/disp32
    28649     }
    28650     # copy-object
    28651     {
    28652       # if (!string-equal?(stmt->operation, "copy-object")) break
    28653       (string-equal? %ecx "copy-object")  # => eax
    28654       3d/compare-eax-and 0/imm32/false
    28655       0f 84/jump-if-= break/disp32
    28656       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28657       e9/jump $emit-subx-stmt:end/disp32
    28658     }
    28659     # clear-object
    28660     {
    28661       # if (!string-equal?(stmt->operation, "clear-object")) break
    28662       (string-equal? %ecx "clear-object")  # => eax
    28663       3d/compare-eax-and 0/imm32/false
    28664       0f 84/jump-if-= break/disp32
    28665       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28666       e9/jump $emit-subx-stmt:end/disp32
    28667     }
    28668     # allocate array
    28669     {
    28670       # if (!string-equal?(stmt->operation, "populate")) break
    28671       (string-equal? %ecx "populate")  # => eax
    28672       3d/compare-eax-and 0/imm32/false
    28673       0f 84/jump-if-= break/disp32
    28674       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28675       e9/jump $emit-subx-stmt:end/disp32
    28676     }
    28677     # allocate stream
    28678     {
    28679       # if (!string-equal?(stmt->operation, "populate-stream")) break
    28680       (string-equal? %ecx "populate-stream")  # => eax
    28681       3d/compare-eax-and 0/imm32/false
    28682       0f 84/jump-if-= break/disp32
    28683       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28684       e9/jump $emit-subx-stmt:end/disp32
    28685     }
    28686     # read from stream
    28687     {
    28688       # if (!string-equal?(stmt->operation, "read-from-stream")) break
    28689       (string-equal? %ecx "read-from-stream")  # => eax
    28690       3d/compare-eax-and 0/imm32/false
    28691       0f 84/jump-if-= break/disp32
    28692       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28693       e9/jump $emit-subx-stmt:end/disp32
    28694     }
    28695     # write to stream
    28696     {
    28697       # if (!string-equal?(stmt->operation, "write-to-stream")) break
    28698       (string-equal? %ecx "write-to-stream")  # => eax
    28699       3d/compare-eax-and 0/imm32/false
    28700       0f 84/jump-if-= break/disp32
    28701       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28702       e9/jump $emit-subx-stmt:end/disp32
    28703     }
    28704     # - optimizations
    28705     # if copy instruction has same register in source and destination, emit nothing
    28706     (redundant-copy? *(ebp+0xc))  # => eax
    28707     3d/compare-eax-and 0/imm32/false
    28708     75/jump-if-!= $emit-subx-stmt:end/disp8
    28709     # - if stmt matches a primitive, emit it
    28710     {
    28711 $emit-subx-stmt:check-for-primitive:
    28712       # var curr/eax: (addr primitive)
    28713       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
    28714       3d/compare-eax-and 0/imm32
    28715       74/jump-if-= break/disp8
    28716 $emit-subx-stmt:primitive:
    28717       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
    28718       e9/jump $emit-subx-stmt:end/disp32
    28719     }
    28720     # - otherwise emit a call
    28721     # TODO: type-checking
    28722 $emit-subx-stmt:call:
    28723     (emit-call *(ebp+8) *(ebp+0xc))
    28724 $emit-subx-stmt:end:
    28725     # . restore registers
    28726     59/pop-to-ecx
    28727     58/pop-to-eax
    28728     # . epilogue
    28729     89/<- %esp 5/r32/ebp
    28730     5d/pop-to-ebp
    28731     c3/return
    28732
    28733 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
    28734     # . prologue
    28735     55/push-ebp
    28736     89/<- %ebp 4/r32/esp
    28737     # . save registers
    28738     56/push-esi
    28739     57/push-edi
    28740     # esi = stmt
    28741     8b/-> *(ebp+8) 6/r32/esi
    28742     # if stmt->operation != "copy" return false
    28743     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    28744     (string-equal? %eax "copy")  # => eax
    28745     3d/compare-eax-and 0/imm32/false
    28746     0f 84/jump-if-= $redundant-copy?:end/disp32
    28747     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
    28748     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28749     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28750     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28751     # . if output-reg == null, return false
    28752     3d/compare-eax-and 0/imm32
    28753     74/jump-if-= $redundant-copy?:end/disp8
    28754     89/<- %edi 0/r32/eax
    28755     # return (inout->value->register == output->value->register)
    28756     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28757     # . if inout->is-deref return false
    28758     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
    28759     {
    28760       74/jump-if-= break/disp8
    28761       b8/copy-to-eax 0/imm32/false
    28762       e9/jump $redundant-copy?:end/disp32
    28763     }
    28764     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28765     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28766     # . if inout-reg == null, return false
    28767     3d/compare-eax-and 0/imm32
    28768     74/jump-if-= $redundant-copy?:end/disp8
    28769     (string-equal? %eax %edi)  # => eax
    28770 $redundant-copy?:end:
    28771     # . restore registers
    28772     5f/pop-to-edi
    28773     5e/pop-to-esi
    28774     # . epilogue
    28775     89/<- %esp 5/r32/ebp
    28776     5d/pop-to-ebp
    28777     c3/return
    28778
    28779 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28780     # . prologue
    28781     55/push-ebp
    28782     89/<- %ebp 4/r32/esp
    28783     # . save registers
    28784     50/push-eax
    28785     51/push-ecx
    28786     52/push-edx
    28787     53/push-ebx
    28788     56/push-esi
    28789     # esi = stmt
    28790     8b/-> *(ebp+0xc) 6/r32/esi
    28791     # var base/ebx: (addr var) = stmt->inouts[0]->value
    28792     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28793     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28794     89/<- %ebx 0/r32/eax
    28795     # var elemsize/ecx: int = array-element-size(base)
    28796     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    28797     89/<- %ecx 0/r32/eax
    28798     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
    28799     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28800     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28801     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28802     89/<- %edx 0/r32/eax
    28803     # if elemsize == 1
    28804     {
    28805       81 7/subop/compare %ecx 1/imm32
    28806       75/jump-if-!= break/disp8
    28807 $translate-mu-length-stmt:size-1:
    28808       (emit-save-size-to *(ebp+8) %ebx %edx)
    28809       e9/jump $translate-mu-length-stmt:end/disp32
    28810     }
    28811     # if elemsize is a power of 2 less than 256
    28812     {
    28813       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    28814       3d/compare-eax-and 0/imm32/false
    28815       74/jump-if-= break/disp8
    28816       81 7/subop/compare %ecx 0xff/imm32
    28817       7f/jump-if-> break/disp8
    28818 $translate-mu-length-stmt:size-power-of-2:
    28819       (emit-save-size-to *(ebp+8) %ebx %edx)
    28820       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
    28821       e9/jump $translate-mu-length-stmt:end/disp32
    28822     }
    28823     # otherwise, the complex case
    28824     # . emit register spills
    28825     {
    28826 $translate-mu-length-stmt:complex:
    28827       (string-equal? %edx "eax")  # => eax
    28828       3d/compare-eax-and 0/imm32/false
    28829       75/break-if-!= break/disp8
    28830       (emit-indent *(ebp+8) *Curr-block-depth)
    28831       (write-buffered *(ebp+8) "50/push-eax\n")
    28832     }
    28833     {
    28834       (string-equal? %edx "ecx")  # => eax
    28835       3d/compare-eax-and 0/imm32/false
    28836       75/break-if-!= break/disp8
    28837       (emit-indent *(ebp+8) *Curr-block-depth)
    28838       (write-buffered *(ebp+8) "51/push-ecx\n")
    28839     }
    28840     {
    28841       (string-equal? %edx "edx")  # => eax
    28842       3d/compare-eax-and 0/imm32/false
    28843       75/break-if-!= break/disp8
    28844       (emit-indent *(ebp+8) *Curr-block-depth)
    28845       (write-buffered *(ebp+8) "52/push-edx\n")
    28846     }
    28847     # .
    28848     (emit-save-size-to *(ebp+8) %ebx "eax")
    28849     (emit-indent *(ebp+8) *Curr-block-depth)
    28850     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
    28851     (emit-indent *(ebp+8) *Curr-block-depth)
    28852     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
    28853     (write-int32-hex-buffered *(ebp+8) %ecx)
    28854     (write-buffered *(ebp+8) "/imm32\n")
    28855     (emit-indent *(ebp+8) *Curr-block-depth)
    28856     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
    28857     {
    28858       (string-equal? %edx "eax")  # => eax
    28859       3d/compare-eax-and 0/imm32/false
    28860       75/break-if-!= break/disp8
    28861       (emit-indent *(ebp+8) *Curr-block-depth)
    28862       (write-buffered *(ebp+8) "89/<- %")
    28863       (write-buffered *(ebp+8) %edx)
    28864       (write-buffered *(ebp+8) " 0/r32/eax\n")
    28865     }
    28866     # . emit register restores
    28867     {
    28868       (string-equal? %edx "edx")  # => eax
    28869       3d/compare-eax-and 0/imm32/false
    28870       75/break-if-!= break/disp8
    28871       (emit-indent *(ebp+8) *Curr-block-depth)
    28872       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
    28873     }
    28874     {
    28875       (string-equal? %edx "ecx")  # => eax
    28876       3d/compare-eax-and 0/imm32/false
    28877       75/break-if-!= break/disp8
    28878       (emit-indent *(ebp+8) *Curr-block-depth)
    28879       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
    28880     }
    28881     {
    28882       (string-equal? %edx "eax")  # => eax
    28883       3d/compare-eax-and 0/imm32/false
    28884       75/break-if-!= break/disp8
    28885       (emit-indent *(ebp+8) *Curr-block-depth)
    28886       (write-buffered *(ebp+8) "58/pop-to-eax\n")
    28887     }
    28888 $translate-mu-length-stmt:end:
    28889     # . restore registers
    28890     5e/pop-to-esi
    28891     5b/pop-to-ebx
    28892     5a/pop-to-edx
    28893     59/pop-to-ecx
    28894     58/pop-to-eax
    28895     # . epilogue
    28896     89/<- %esp 5/r32/ebp
    28897     5d/pop-to-ebp
    28898     c3/return
    28899
    28900 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    28901     # . prologue
    28902     55/push-ebp
    28903     89/<- %ebp 4/r32/esp
    28904     #
    28905     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    28906     (size-of-type-id-as-array-element %eax)  # => eax
    28907 $array-element-size:end:
    28908     # . epilogue
    28909     89/<- %esp 5/r32/ebp
    28910     5d/pop-to-ebp
    28911     c3/return
    28912
    28913 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    28914     # precondition: n is positive
    28915     # . prologue
    28916     55/push-ebp
    28917     89/<- %ebp 4/r32/esp
    28918     #
    28919     8b/-> *(ebp+8) 0/r32/eax
    28920     # var t/eax: (addr type-tree)
    28921     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    28922     # if t == 0 abort
    28923     3d/compare-eax-with 0/imm32
    28924     0f 84/jump-if-== $array-element-type-id:error0/disp32
    28925     # if t->is-atom? abort
    28926     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    28927     0f 85/jump-if-!= $array-element-type-id:error1/disp32
    28928     # if (t->left == addr) t = t->right
    28929     {
    28930       50/push-eax
    28931       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    28932       (simple-mu-type? %eax 2)  # addr => eax
    28933       3d/compare-eax-with 0/imm32/false
    28934       58/pop-to-eax
    28935       74/jump-if-= break/disp8
    28936 $array-element-type-id:skip-addr:
    28937       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    28938     }
    28939     # if t == 0 abort
    28940     3d/compare-eax-with 0/imm32
    28941     0f 84/jump-if-= $array-element-type-id:error2/disp32
    28942     # if t->is-atom? abort
    28943     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    28944     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    28945     # if t->left != array abort
    28946     {
    28947       50/push-eax
    28948       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    28949       (simple-mu-type? %eax 3)  # array => eax
    28950       3d/compare-eax-with 0/imm32/false
    28951       58/pop-to-eax
    28952 $array-element-type-id:no-array:
    28953       0f 84/jump-if-= $array-element-type-id:error2/disp32
    28954     }
    28955 $array-element-type-id:skip-array:
    28956     # t = t->right
    28957     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    28958     # if t == 0 abort
    28959     3d/compare-eax-with 0/imm32
    28960     0f 84/jump-if-= $array-element-type-id:error2/disp32
    28961     # if t->is-atom? abort
    28962     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    28963     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    28964     # t = t->left
    28965     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    28966     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
    28967     # if (t->is-atom == false) t = lookup(t->left)
    28968     {
    28969       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    28970       75/jump-if-!= break/disp8
    28971       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    28972     }
    28973     # return t->value
    28974     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    28975 $array-element-type-id:end:
    28976     # . epilogue
    28977     89/<- %esp 5/r32/ebp
    28978     5d/pop-to-ebp
    28979     c3/return
    28980
    28981 $array-element-type-id:error0:
    28982     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    28983     50/push-eax
    28984     8b/-> *(ebp+8) 0/r32/eax
    28985     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    28986     (write-buffered *(ebp+0xc) %eax)
    28987     58/pop-to-eax
    28988     (write-buffered *(ebp+0xc) "' has no type\n")
    28989     (flush *(ebp+0xc))
    28990     (stop *(ebp+0x10) 1)
    28991     # never gets here
    28992
    28993 $array-element-type-id:error1:
    28994     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    28995     50/push-eax
    28996     8b/-> *(ebp+8) 0/r32/eax
    28997     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    28998     (write-buffered *(ebp+0xc) %eax)
    28999     58/pop-to-eax
    29000     (write-buffered *(ebp+0xc) "' has atomic type ")
    29001     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29002     (write-buffered *(ebp+0xc) Newline)
    29003     (flush *(ebp+0xc))
    29004     (stop *(ebp+0x10) 1)
    29005     # never gets here
    29006
    29007 $array-element-type-id:error2:
    29008     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29009     50/push-eax
    29010     8b/-> *(ebp+8) 0/r32/eax
    29011     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29012     (write-buffered *(ebp+0xc) %eax)
    29013     58/pop-to-eax
    29014     (write-buffered *(ebp+0xc) "' has non-array type\n")
    29015     (flush *(ebp+0xc))
    29016     (stop *(ebp+0x10) 1)
    29017     # never gets here
    29018
    29019 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
    29020     # . prologue
    29021     55/push-ebp
    29022     89/<- %ebp 4/r32/esp
    29023     # eax = t
    29024     8b/-> *(ebp+8) 0/r32/eax
    29025     # if t is 'byte', size is 1
    29026     3d/compare-eax-and 8/imm32/byte
    29027     {
    29028       75/jump-if-!= break/disp8
    29029       b8/copy-to-eax 1/imm32
    29030       eb/jump $size-of-type-id-as-array-element:end/disp8
    29031     }
    29032     # otherwise proceed as usual
    29033     (size-of-type-id %eax)  # => eax
    29034 $size-of-type-id-as-array-element:end:
    29035     # . epilogue
    29036     89/<- %esp 5/r32/ebp
    29037     5d/pop-to-ebp
    29038     c3/return
    29039
    29040 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
    29041     # . prologue
    29042     55/push-ebp
    29043     89/<- %ebp 4/r32/esp
    29044     # . save registers
    29045     50/push-eax
    29046     53/push-ebx
    29047     # ebx = base
    29048     8b/-> *(ebp+0xc) 3/r32/ebx
    29049     (emit-indent *(ebp+8) *Curr-block-depth)
    29050     (write-buffered *(ebp+8) "8b/-> *")
    29051     # if base is an (addr array ...) in a register
    29052     {
    29053       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
    29054       74/jump-if-= break/disp8
    29055 $emit-save-size-to:emit-base-from-register:
    29056       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29057       (write-buffered *(ebp+8) %eax)
    29058       eb/jump $emit-save-size-to:emit-output/disp8
    29059     }
    29060     # otherwise if base is an (array ...) on the stack
    29061     {
    29062       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
    29063       74/jump-if-= break/disp8
    29064 $emit-save-size-to:emit-base-from-stack:
    29065       (write-buffered *(ebp+8) "(ebp+")
    29066       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29067       (write-buffered *(ebp+8) ")")
    29068     }
    29069 $emit-save-size-to:emit-output:
    29070     (write-buffered *(ebp+8) " ")
    29071     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    29072     (write-int32-hex-buffered *(ebp+8) *eax)
    29073     (write-buffered *(ebp+8) "/r32\n")
    29074 $emit-save-size-to:end:
    29075     # . restore registers
    29076     5b/pop-to-ebx
    29077     58/pop-to-eax
    29078     # . epilogue
    29079     89/<- %esp 5/r32/ebp
    29080     5d/pop-to-ebp
    29081     c3/return
    29082
    29083 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
    29084     # . prologue
    29085     55/push-ebp
    29086     89/<- %ebp 4/r32/esp
    29087     # . save registers
    29088     50/push-eax
    29089     #
    29090     (emit-indent *(ebp+8) *Curr-block-depth)
    29091     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
    29092     (write-buffered *(ebp+8) *(ebp+0xc))
    29093     (write-buffered *(ebp+8) Space)
    29094     (num-shift-rights *(ebp+0x10))  # => eax
    29095     (write-int32-hex-buffered *(ebp+8) %eax)
    29096     (write-buffered *(ebp+8) "/imm8\n")
    29097 $emit-divide-by-shift-right:end:
    29098     # . restore registers
    29099     58/pop-to-eax
    29100     # . epilogue
    29101     89/<- %esp 5/r32/ebp
    29102     5d/pop-to-ebp
    29103     c3/return
    29104
    29105 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29106     # . prologue
    29107     55/push-ebp
    29108     89/<- %ebp 4/r32/esp
    29109     # . save registers
    29110     50/push-eax
    29111     56/push-esi
    29112     # esi = stmt
    29113     8b/-> *(ebp+0xc) 6/r32/esi
    29114     #
    29115     (emit-indent *(ebp+8) *Curr-block-depth)
    29116     (write-buffered *(ebp+8) "8a/byte->")
    29117     # emit stmt->inouts[0]
    29118     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29119     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29120     # emit /r32 for stmt->outputs[0]->register
    29121     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29122     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29123     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29124     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    29125     (write-buffered *(ebp+8) Space)
    29126     (write-int32-hex-buffered *(ebp+8) *eax)
    29127     (write-buffered *(ebp+8) "/r32\n")
    29128     # clear rest of register
    29129     (emit-indent *(ebp+8) *Curr-block-depth)
    29130     (write-buffered *(ebp+8) "81 4/subop/and %")
    29131     8b/-> *(ebp+0xc) 0/r32/eax
    29132     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29133     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29134     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29135     (write-buffered *(ebp+8) %eax)
    29136     (write-buffered *(ebp+8) " 0xff/imm32\n")
    29137 $translate-mu-copy-byte-stmt:end:
    29138     # . restore registers
    29139     5e/pop-to-esi
    29140     58/pop-to-eax
    29141     # . epilogue
    29142     89/<- %esp 5/r32/ebp
    29143     5d/pop-to-ebp
    29144     c3/return
    29145
    29146 # a little different from other translate- functions; notice the extra 'fn' argument
    29147 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    29148     # . prologue
    29149     55/push-ebp
    29150     89/<- %ebp 4/r32/esp
    29151     # . save registers
    29152     53/push-ebx
    29153     # ebx = stmt
    29154     8b/-> *(ebp+0xc) 3/r32/ebx
    29155     # var base/ebx: (addr var) = stmt->inouts[0]
    29156     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29157     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29158     89/<- %ebx 0/r32/eax
    29159     # emit bounds-check
    29160     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    29161     # if (var->register) do one thing
    29162     {
    29163       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29164       74/jump-if-= break/disp8
    29165       # TODO: ensure there's no dereference
    29166       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29167       eb/jump $translate-mu-index-stmt:end/disp8
    29168     }
    29169     # if (var->offset) do a different thing
    29170     {
    29171       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
    29172       74/jump-if-= break/disp8
    29173       # TODO: ensure there's no dereference
    29174       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29175       eb/jump $translate-mu-index-stmt:end/disp8
    29176     }
    29177 $translate-mu-index-stmt:end:
    29178     # . restore registers
    29179     5b/pop-to-ebx
    29180     # . epilogue
    29181     89/<- %esp 5/r32/ebp
    29182     5d/pop-to-ebp
    29183     c3/return
    29184
    29185 $translate-mu-index-stmt:error1:
    29186     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
    29187     (flush *(ebp+0x14))
    29188     (stop *(ebp+0x18) 1)
    29189     # never gets here
    29190
    29191 $translate-mu-index-stmt:error2:
    29192     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
    29193     (flush *(ebp+0x14))
    29194     (stop *(ebp+0x18) 1)
    29195     # never gets here
    29196
    29197 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29198     # . prologue
    29199     55/push-ebp
    29200     89/<- %ebp 4/r32/esp
    29201     # . save registers
    29202     50/push-eax
    29203     51/push-ecx
    29204     52/push-edx
    29205     53/push-ebx
    29206     # ecx = stmt
    29207     8b/-> *(ebp+0xc) 1/r32/ecx
    29208     #
    29209     (emit-indent *(ebp+8) *Curr-block-depth)
    29210     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
    29211 $emit-mu-index-bounds-check:compute-base:
    29212     # var base/ebx: (addr var) = inouts[0]
    29213     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29214     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29215     89/<- %ebx 0/r32/eax
    29216 $emit-mu-index-bounds-check:emit-index:
    29217     # var index/edx: (addr var) = inouts[1]
    29218     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29219     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29220     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29221     89/<- %edx 0/r32/eax
    29222     # if index->register, print its code
    29223     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29224     {
    29225       0f 84/jump-if-= break/disp32
    29226 $emit-mu-index-bounds-check:emit-register-index:
    29227       (write-buffered *(ebp+8) "%")
    29228       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29229       (write-buffered *(ebp+8) %eax)
    29230       eb/jump $emit-mu-index-bounds-check:index-done/disp8
    29231     }
    29232     # otherwise if index is a literal, print it
    29233 $emit-mu-index-bounds-check:emit-literal-index:
    29234     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29235     (simple-mu-type? %eax 0)  # => eax
    29236     3d/compare-eax-and 0/imm32/false
    29237     {
    29238       0f 84/jump-if-= break/disp32
    29239       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29240       (write-buffered *(ebp+8) %eax)
    29241     }
    29242 $emit-mu-index-bounds-check:index-done:
    29243     (write-buffered *(ebp+8) " ")
    29244 $emit-mu-index-bounds-check:emit-element-size:
    29245     # if index is a literal or int, print size of array element
    29246     {
    29247       {
    29248         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29249         (simple-mu-type? %eax 0)  # literal => eax
    29250         3d/compare-eax-and 0/imm32/false
    29251         75/jump-if-!= break/disp8
    29252         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29253         (simple-mu-type? %eax 1)  # int => eax
    29254         3d/compare-eax-and 0/imm32/false
    29255         75/jump-if-!= break/disp8
    29256         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
    29257       }
    29258 $emit-mu-index-bounds-check:emit-int-register-index:
    29259       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
    29260       (write-int32-hex-buffered *(ebp+8) %eax)
    29261       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
    29262     }
    29263 $emit-mu-index-bounds-check:emit-element-size-offset:
    29264     # if index has type (offset ...), print "1"
    29265     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29266     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29267     {
    29268       75/jump-if-!= break/disp8
    29269       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29270       (simple-mu-type? %eax 7)  # => eax
    29271       3d/compare-eax-and 0/imm32/false
    29272       {
    29273         0f 84/jump-if-= break/disp32
    29274 $emit-mu-index-bounds-check:emit-offset-register-index:
    29275         (write-buffered *(ebp+8) "1")
    29276       }
    29277     }
    29278 $emit-mu-index-bounds-check:emit-base:
    29279     # if base is in a register, print " *" base->register
    29280     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29281     {
    29282       74/jump-if-= break/disp8
    29283       (write-buffered *(ebp+8) " *")
    29284       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29285       (write-buffered *(ebp+8) %eax)
    29286       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
    29287     }
    29288     # otherwise print " *(ebp+" base->offset ")"
    29289     (write-buffered *(ebp+8) " *(ebp+")
    29290     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29291     (write-buffered *(ebp+8) ")")
    29292 $emit-mu-index-bounds-check:emit-function-name:
    29293     # " \"" function-name "\""
    29294     (write-buffered *(ebp+8) " \"")
    29295     8b/-> *(ebp+0x10) 1/r32/ecx
    29296     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    29297     (write-buffered *(ebp+8) %eax)
    29298     (write-buffered *(ebp+8) "\"")
    29299 $emit-mu-index-bounds-check:emit-array-name:
    29300     # " \"" base->name "\""
    29301     (write-buffered *(ebp+8) " \"")
    29302     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    29303     (write-buffered *(ebp+8) %eax)
    29304     (write-buffered *(ebp+8) "\")\n")
    29305 $emit-mu-index-bounds-check:end:
    29306     # . restore registers
    29307     5b/pop-to-ebx
    29308     5a/pop-to-edx
    29309     59/pop-to-ecx
    29310     58/pop-to-eax
    29311     # . epilogue
    29312     89/<- %esp 5/r32/ebp
    29313     5d/pop-to-ebp
    29314     c3/return
    29315
    29316 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29317     # . prologue
    29318     55/push-ebp
    29319     89/<- %ebp 4/r32/esp
    29320     # . save registers
    29321     50/push-eax
    29322     51/push-ecx
    29323     52/push-edx
    29324     53/push-ebx
    29325     #
    29326     (emit-indent *(ebp+8) *Curr-block-depth)
    29327     (write-buffered *(ebp+8) "8d/copy-address *(")
    29328     # TODO: ensure inouts[0] is in a register and not dereferenced
    29329 $translate-mu-index-stmt-with-array-in-register:emit-base:
    29330     # ecx = stmt
    29331     8b/-> *(ebp+0xc) 1/r32/ecx
    29332     # var base/ebx: (addr var) = inouts[0]
    29333     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29334     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29335     89/<- %ebx 0/r32/eax
    29336     # print base->register " + "
    29337     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29338     (write-buffered *(ebp+8) %eax)
    29339     (write-buffered *(ebp+8) " + ")
    29340     # var index/edx: (addr var) = inouts[1]
    29341     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29342     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29343     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29344     89/<- %edx 0/r32/eax
    29345     # if index->register
    29346     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29347     {
    29348       0f 84/jump-if-= break/disp32
    29349 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
    29350       # if index is an int
    29351       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29352       (simple-mu-type? %eax 1)  # int => eax
    29353       3d/compare-eax-and 0/imm32/false
    29354       {
    29355         0f 84/jump-if-= break/disp32
    29356 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
    29357         # print index->register "<<" log2(array-element-size(base)) " + 4) "
    29358         # . index->register "<<"
    29359         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29360         (write-buffered *(ebp+8) %eax)
    29361         (write-buffered *(ebp+8) "<<")
    29362         # . log2(array-element-size(base->type))
    29363         # we know size is a power of 2
    29364         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29365         (num-shift-rights %eax)  # => eax
    29366         (write-int32-hex-buffered *(ebp+8) %eax)
    29367         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
    29368       }
    29369       # if index->type is any other atom, abort
    29370       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29371       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29372       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29373       # if index has type (offset ...)
    29374       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29375       (simple-mu-type? %eax 7)  # => eax
    29376       3d/compare-eax-and 0/imm32/false
    29377       {
    29378         0f 84/jump-if-= break/disp32
    29379         # print index->register
    29380 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
    29381         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29382         (write-buffered *(ebp+8) %eax)
    29383       }
    29384 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
    29385       (write-buffered *(ebp+8) " + 4) ")
    29386       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29387     }
    29388     # otherwise if index is a literal
    29389     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29390     (simple-mu-type? %eax 0)  # => eax
    29391     3d/compare-eax-and 0/imm32/false
    29392     {
    29393       0f 84/jump-if-= break/disp32
    29394 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
    29395       # var index-value/edx: int = parse-hex-int(index->name)
    29396       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29397       (parse-hex-int %eax)  # => eax
    29398       89/<- %edx 0/r32/eax
    29399       # offset = idx-value * array-element-size(base->type)
    29400       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29401       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29402       # offset += 4 for array size
    29403       05/add-to-eax 4/imm32
    29404       # TODO: check edx for overflow
    29405       # print offset
    29406       (write-int32-hex-buffered *(ebp+8) %eax)
    29407       (write-buffered *(ebp+8) ") ")
    29408       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29409     }
    29410     # otherwise abort
    29411     e9/jump $translate-mu-index-stmt:error1/disp32
    29412 $translate-mu-index-stmt-with-array-in-register:emit-output:
    29413     # outputs[0] "/r32"
    29414     8b/-> *(ebp+0xc) 1/r32/ecx
    29415     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29416     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29417     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29418     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29419     (write-int32-hex-buffered *(ebp+8) *eax)
    29420     (write-buffered *(ebp+8) "/r32\n")
    29421 $translate-mu-index-stmt-with-array-in-register:end:
    29422     # . restore registers
    29423     5b/pop-to-ebx
    29424     5a/pop-to-edx
    29425     59/pop-to-ecx
    29426     58/pop-to-eax
    29427     # . epilogue
    29428     89/<- %esp 5/r32/ebp
    29429     5d/pop-to-ebp
    29430     c3/return
    29431
    29432 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29433     # . prologue
    29434     55/push-ebp
    29435     89/<- %ebp 4/r32/esp
    29436     # . save registers
    29437     50/push-eax
    29438     51/push-ecx
    29439     52/push-edx
    29440     53/push-ebx
    29441     #
    29442     (emit-indent *(ebp+8) *Curr-block-depth)
    29443     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
    29444     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
    29445     8b/-> *(ebp+0xc) 0/r32/eax
    29446     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29447     89/<- %edx 0/r32/eax
    29448     # var base/ecx: (addr var) = lookup(curr->value)
    29449     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29450     89/<- %ecx 0/r32/eax
    29451     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
    29452     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29453     # var index/edx: (handle var) = curr2->value
    29454     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29455     89/<- %edx 0/r32/eax
    29456     # if index->register
    29457     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29458     {
    29459       0f 84/jump-if-= break/disp32
    29460 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
    29461       # if index is an int
    29462       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29463       (simple-mu-type? %eax 1)  # int => eax
    29464       3d/compare-eax-and 0/imm32/false
    29465       {
    29466         0f 84/jump-if-= break/disp32
    29467 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
    29468         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
    29469         # . inouts[1]->register "<<"
    29470         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29471         (write-buffered *(ebp+8) %eax)
    29472         (write-buffered *(ebp+8) "<<")
    29473         # . log2(array-element-size(base))
    29474         # TODO: ensure size is a power of 2
    29475         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29476         (num-shift-rights %eax)  # => eax
    29477         (write-int32-hex-buffered *(ebp+8) %eax)
    29478         #
    29479         (write-buffered *(ebp+8) " + ")
    29480         #
    29481         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
    29482         05/add-to-eax 4/imm32  # for array length
    29483         (write-int32-hex-buffered *(ebp+8) %eax)
    29484         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
    29485       }
    29486       # if index->type is any other atom, abort
    29487       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29488       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29489       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29490       # if index has type (offset ...)
    29491       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29492       (simple-mu-type? %eax 7)  # => eax
    29493       3d/compare-eax-and 0/imm32/false
    29494       {
    29495         0f 84/jump-if-= break/disp32
    29496         # print index->register
    29497 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
    29498         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29499         (write-buffered *(ebp+8) %eax)
    29500       }
    29501 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
    29502       (write-buffered *(ebp+8) ") ")
    29503       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29504     }
    29505     # otherwise if index is a literal
    29506     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29507     (simple-mu-type? %eax 0)  # => eax
    29508     3d/compare-eax-and 0/imm32/false
    29509     {
    29510       0f 84/jump-if-= break/disp32
    29511 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
    29512       # var idx-value/edx: int = parse-hex-int(index->name)
    29513       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29514       (parse-hex-int %eax)  # Var-name => eax
    29515       89/<- %edx 0/r32/eax
    29516       # offset = idx-value * array-element-size(base)
    29517       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29518       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29519       # offset += base->offset
    29520       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
    29521       # offset += 4 for array size
    29522       05/add-to-eax 4/imm32
    29523       # TODO: check edx for overflow
    29524       # print offset
    29525       (write-int32-hex-buffered *(ebp+8) %eax)
    29526       (write-buffered *(ebp+8) ") ")
    29527       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29528     }
    29529     # otherwise abort
    29530     e9/jump $translate-mu-index-stmt:error1/disp32
    29531 $translate-mu-index-stmt-with-array-on-stack:emit-output:
    29532     # outputs[0] "/r32"
    29533     8b/-> *(ebp+0xc) 0/r32/eax
    29534     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29535     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29536     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29537     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29538     (write-int32-hex-buffered *(ebp+8) *eax)
    29539     (write-buffered *(ebp+8) "/r32\n")
    29540 $translate-mu-index-stmt-with-array-on-stack:end:
    29541     # . restore registers
    29542     5b/pop-to-ebx
    29543     5a/pop-to-edx
    29544     59/pop-to-ecx
    29545     58/pop-to-eax
    29546     # . epilogue
    29547     89/<- %esp 5/r32/ebp
    29548     5d/pop-to-ebp
    29549     c3/return
    29550
    29551 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29552     # . prologue
    29553     55/push-ebp
    29554     89/<- %ebp 4/r32/esp
    29555     # . save registers
    29556     50/push-eax
    29557     51/push-ecx
    29558     52/push-edx
    29559     53/push-ebx
    29560     #
    29561     (emit-indent *(ebp+8) *Curr-block-depth)
    29562     (write-buffered *(ebp+8) "69/multiply")
    29563     # ecx = stmt
    29564     8b/-> *(ebp+0xc) 1/r32/ecx
    29565     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
    29566     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29567     89/<- %ebx 0/r32/eax
    29568 $translate-mu-compute-index-stmt:emit-index:
    29569     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29570     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29571     (write-buffered *(ebp+8) Space)
    29572 $translate-mu-compute-index-stmt:emit-elem-size:
    29573     # var base/ebx: (addr var)
    29574     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
    29575     89/<- %ebx 0/r32/eax
    29576     # print array-element-size(base)
    29577     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29578     (write-int32-hex-buffered *(ebp+8) %eax)
    29579     (write-buffered *(ebp+8) "/imm32 ")
    29580 $translate-mu-compute-index-stmt:emit-output:
    29581     # outputs[0] "/r32"
    29582     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29583     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29584     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29585     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29586     (write-int32-hex-buffered *(ebp+8) *eax)
    29587     (write-buffered *(ebp+8) "/r32\n")
    29588 $translate-mu-compute-index-stmt:end:
    29589     # . restore registers
    29590     5b/pop-to-ebx
    29591     5a/pop-to-edx
    29592     59/pop-to-ecx
    29593     58/pop-to-eax
    29594     # . epilogue
    29595     89/<- %esp 5/r32/ebp
    29596     5d/pop-to-ebp
    29597     c3/return
    29598
    29599 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
    29600     # . prologue
    29601     55/push-ebp
    29602     89/<- %ebp 4/r32/esp
    29603     # . save registers
    29604     50/push-eax
    29605     51/push-ecx
    29606     52/push-edx
    29607     #
    29608     (emit-indent *(ebp+8) *Curr-block-depth)
    29609     (write-buffered *(ebp+8) "8d/copy-address ")
    29610     # ecx = stmt
    29611     8b/-> *(ebp+0xc) 1/r32/ecx
    29612     # var offset/edx: int = get offset of stmt
    29613     (mu-get-offset %ecx)  # => eax
    29614     89/<- %edx 0/r32/eax
    29615     # var base/eax: (addr var) = stmt->inouts->value
    29616     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29617     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29618     # if base is in a register
    29619     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    29620     {
    29621       0f 84/jump-if-= break/disp32
    29622 $translate-mu-get-stmt:emit-register-input:
    29623       # emit "*(" base->register " + " offset ") "
    29624       (write-buffered *(ebp+8) "*(")
    29625       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29626       (write-buffered *(ebp+8) %eax)
    29627       (write-buffered *(ebp+8) " + ")
    29628       (write-int32-hex-buffered *(ebp+8) %edx)
    29629       (write-buffered *(ebp+8) ") ")
    29630       e9/jump $translate-mu-get-stmt:emit-output/disp32
    29631     }
    29632     # otherwise base is on the stack
    29633     {
    29634 $translate-mu-get-stmt:emit-stack-input:
    29635       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
    29636       (write-buffered *(ebp+8) "*(ebp+")
    29637       03/add *(eax+0x14) 2/r32/edx  # Var-offset
    29638       (write-int32-hex-buffered *(ebp+8) %edx)
    29639       (write-buffered *(ebp+8) ") ")
    29640       eb/jump $translate-mu-get-stmt:emit-output/disp8
    29641     }
    29642 $translate-mu-get-stmt:emit-output:
    29643     # var output/eax: (addr var) = stmt->outputs->value
    29644     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29645     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29646     # emit offset->register "/r32"
    29647     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29648     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29649     (write-int32-hex-buffered *(ebp+8) *eax)
    29650     (write-buffered *(ebp+8) "/r32\n")
    29651 $translate-mu-get-stmt:end:
    29652     # . restore registers
    29653     5a/pop-to-edx
    29654     59/pop-to-ecx
    29655     58/pop-to-eax
    29656     # . epilogue
    29657     89/<- %esp 5/r32/ebp
    29658     5d/pop-to-ebp
    29659     c3/return
    29660
    29661 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29662     # . prologue
    29663     55/push-ebp
    29664     89/<- %ebp 4/r32/esp
    29665     # . save registers
    29666     50/push-eax
    29667     #
    29668     (emit-indent *(ebp+8) *Curr-block-depth)
    29669     (write-buffered *(ebp+8) "(copy-bytes")
    29670     # eax = stmt
    29671     8b/-> *(ebp+0xc) 0/r32/eax
    29672     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
    29673     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29674     (emit-subx-call-operand *(ebp+8) %eax)
    29675     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
    29676     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29677     (emit-subx-call-operand *(ebp+8) %eax)
    29678     # emit size of inouts
    29679     (write-buffered *(ebp+8) Space)
    29680     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29681     (write-int32-hex-buffered *(ebp+8) %eax)
    29682     (write-buffered *(ebp+8) ")\n")
    29683 $translate-mu-copy-object-stmt:end:
    29684     # . restore registers
    29685     58/pop-to-eax
    29686     # . epilogue
    29687     89/<- %esp 5/r32/ebp
    29688     5d/pop-to-ebp
    29689     c3/return
    29690
    29691 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29692     # . prologue
    29693     55/push-ebp
    29694     89/<- %ebp 4/r32/esp
    29695     # . save registers
    29696     50/push-eax
    29697     #
    29698     (emit-indent *(ebp+8) *Curr-block-depth)
    29699     (write-buffered *(ebp+8) "(zero-out")
    29700     # eax = stmt
    29701     8b/-> *(ebp+0xc) 0/r32/eax
    29702     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
    29703     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29704     #
    29705     (emit-subx-call-operand *(ebp+8) %eax)
    29706     (write-buffered *(ebp+8) Space)
    29707     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29708     (write-int32-hex-buffered *(ebp+8) %eax)
    29709     (write-buffered *(ebp+8) ")\n")
    29710 $translate-mu-clear-object-stmt:end:
    29711     # . restore registers
    29712     58/pop-to-eax
    29713     # . epilogue
    29714     89/<- %esp 5/r32/ebp
    29715     5d/pop-to-ebp
    29716     c3/return
    29717
    29718 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29719     # . prologue
    29720     55/push-ebp
    29721     89/<- %ebp 4/r32/esp
    29722     # . save registers
    29723     50/push-eax
    29724     56/push-esi
    29725     57/push-edi
    29726     # esi = stmt
    29727     8b/-> *(ebp+0xc) 6/r32/esi
    29728     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29729     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29730     89/<- %edi 0/r32/eax
    29731     #
    29732     (emit-indent *(ebp+8) *Curr-block-depth)
    29733     (write-buffered *(ebp+8) "(allocate Heap ")
    29734     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29735     (write-int32-hex-buffered *(ebp+8) %eax)
    29736     (emit-subx-call-operand *(ebp+8) %edi)
    29737     (write-buffered *(ebp+8) ")\n")
    29738 $translate-mu-allocate-stmt:end:
    29739     # . restore registers
    29740     5f/pop-to-edi
    29741     5e/pop-to-esi
    29742     58/pop-to-eax
    29743     # . epilogue
    29744     89/<- %esp 5/r32/ebp
    29745     5d/pop-to-ebp
    29746     c3/return
    29747
    29748 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29749     # . prologue
    29750     55/push-ebp
    29751     89/<- %ebp 4/r32/esp
    29752     # var t/eax: (addr type-tree) = s->value->type
    29753     8b/-> *(ebp+8) 0/r32/eax
    29754     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29755     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29756     # TODO: check eax != 0
    29757     # TODO: check !t->is-atom?
    29758     # TODO: check t->left == addr
    29759     # t = t->right
    29760 $addr-handle-payload-size:skip-addr:
    29761     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29762     # TODO: check eax != 0
    29763     # TODO: check !t->is-atom?
    29764     # TODO: check t->left == handle
    29765     # t = t->right
    29766 $addr-handle-payload-size:skip-handle:
    29767     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29768     # TODO: check eax != 0
    29769     # if !t->is-atom? t = t->left
    29770     81 7/subop/compare *eax 0/imm32/false
    29771     {
    29772       75/jump-if-!= break/disp8
    29773       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29774     }
    29775     # TODO: check t->is-atom?
    29776     # return size(t->value)
    29777     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    29778 $addr-handle-payload-size:end:
    29779     # . epilogue
    29780     89/<- %esp 5/r32/ebp
    29781     5d/pop-to-ebp
    29782     c3/return
    29783
    29784 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29785     # . prologue
    29786     55/push-ebp
    29787     89/<- %ebp 4/r32/esp
    29788     # var t/eax: (addr type-tree) = s->value->type
    29789     8b/-> *(ebp+8) 0/r32/eax
    29790     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29791     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29792     # TODO: check eax != 0
    29793     # TODO: check !t->is-atom?
    29794     # TODO: check t->left == addr
    29795     # t = t->right
    29796 $addr-payload-size:skip-addr:
    29797     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29798     # TODO: check eax != 0
    29799     # if !t->is-atom? t = t->left
    29800     81 7/subop/compare *eax 0/imm32/false
    29801     {
    29802       75/jump-if-!= break/disp8
    29803       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29804     }
    29805     # TODO: check t->is-atom?
    29806     # return size(t->value)
    29807     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    29808 $addr-payload-size:end:
    29809     # . epilogue
    29810     89/<- %esp 5/r32/ebp
    29811     5d/pop-to-ebp
    29812     c3/return
    29813
    29814 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29815     # . prologue
    29816     55/push-ebp
    29817     89/<- %ebp 4/r32/esp
    29818     # . save registers
    29819     50/push-eax
    29820     51/push-ecx
    29821     56/push-esi
    29822     57/push-edi
    29823     # esi = stmt
    29824     8b/-> *(ebp+0xc) 6/r32/esi
    29825     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29826     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29827     89/<- %edi 0/r32/eax
    29828     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    29829     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    29830     89/<- %ecx 0/r32/eax
    29831     #
    29832     (emit-indent *(ebp+8) *Curr-block-depth)
    29833     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
    29834     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29835     (write-int32-hex-buffered *(ebp+8) %eax)
    29836     (emit-subx-call-operand *(ebp+8) %ecx)
    29837     (emit-subx-call-operand *(ebp+8) %edi)
    29838     (write-buffered *(ebp+8) ")\n")
    29839 $translate-mu-populate-stmt:end:
    29840     # . restore registers
    29841     5f/pop-to-edi
    29842     5e/pop-to-esi
    29843     59/pop-to-ecx
    29844     58/pop-to-eax
    29845     # . epilogue
    29846     89/<- %esp 5/r32/ebp
    29847     5d/pop-to-ebp
    29848     c3/return
    29849
    29850 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29851     # . prologue
    29852     55/push-ebp
    29853     89/<- %ebp 4/r32/esp
    29854     # . save registers
    29855     50/push-eax
    29856     51/push-ecx
    29857     56/push-esi
    29858     57/push-edi
    29859     # esi = stmt
    29860     8b/-> *(ebp+0xc) 6/r32/esi
    29861     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29862     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29863     89/<- %edi 0/r32/eax
    29864     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    29865     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    29866     89/<- %ecx 0/r32/eax
    29867     #
    29868     (emit-indent *(ebp+8) *Curr-block-depth)
    29869     (write-buffered *(ebp+8) "(new-stream Heap ")
    29870     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29871     (write-int32-hex-buffered *(ebp+8) %eax)
    29872     (emit-subx-call-operand *(ebp+8) %ecx)
    29873     (emit-subx-call-operand *(ebp+8) %edi)
    29874     (write-buffered *(ebp+8) ")\n")
    29875 $translate-mu-populate-stream-stmt:end:
    29876     # . restore registers
    29877     5f/pop-to-edi
    29878     5e/pop-to-esi
    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-read-from-stream-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     51/push-ecx
    29893     56/push-esi
    29894     57/push-edi
    29895     # esi = stmt
    29896     8b/-> *(ebp+0xc) 6/r32/esi
    29897     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    29898     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29899     89/<- %ecx 0/r32/eax
    29900     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    29901     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29902     89/<- %edi 0/r32/eax
    29903     #
    29904     (emit-indent *(ebp+8) *Curr-block-depth)
    29905     (write-buffered *(ebp+8) "(read-from-stream")
    29906     (emit-subx-call-operand *(ebp+8) %ecx)
    29907     (emit-subx-call-operand *(ebp+8) %edi)
    29908     (write-buffered *(ebp+8) Space)
    29909     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29910     (write-int32-hex-buffered *(ebp+8) %eax)
    29911     (write-buffered *(ebp+8) ")\n")
    29912 $translate-mu-read-from-stream-stmt:end:
    29913     # . restore registers
    29914     5f/pop-to-edi
    29915     5e/pop-to-esi
    29916     59/pop-to-ecx
    29917     58/pop-to-eax
    29918     # . epilogue
    29919     89/<- %esp 5/r32/ebp
    29920     5d/pop-to-ebp
    29921     c3/return
    29922
    29923 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29924     # . prologue
    29925     55/push-ebp
    29926     89/<- %ebp 4/r32/esp
    29927     # . save registers
    29928     50/push-eax
    29929     51/push-ecx
    29930     56/push-esi
    29931     57/push-edi
    29932     # esi = stmt
    29933     8b/-> *(ebp+0xc) 6/r32/esi
    29934     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    29935     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29936     89/<- %ecx 0/r32/eax
    29937     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    29938     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29939     89/<- %edi 0/r32/eax
    29940     #
    29941     (emit-indent *(ebp+8) *Curr-block-depth)
    29942     (write-buffered *(ebp+8) "(write-to-stream")
    29943     (emit-subx-call-operand *(ebp+8) %ecx)
    29944     (flush *(ebp+8))
    29945     (emit-subx-call-operand *(ebp+8) %edi)
    29946     (flush *(ebp+8))
    29947     (write-buffered *(ebp+8) Space)
    29948     (flush *(ebp+8))
    29949     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29950     (write-int32-hex-buffered *(ebp+8) %eax)
    29951     (write-buffered *(ebp+8) ")\n")
    29952 $translate-mu-write-to-stream-stmt:end:
    29953     # . restore registers
    29954     5f/pop-to-edi
    29955     5e/pop-to-esi
    29956     59/pop-to-ecx
    29957     58/pop-to-eax
    29958     # . epilogue
    29959     89/<- %esp 5/r32/ebp
    29960     5d/pop-to-ebp
    29961     c3/return
    29962
    29963 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29964     # . prologue
    29965     55/push-ebp
    29966     89/<- %ebp 4/r32/esp
    29967     # var t/eax: (addr type-tree) = s->value->type
    29968     8b/-> *(ebp+8) 0/r32/eax
    29969     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29970     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29971     # TODO: check eax != 0
    29972     # TODO: check !t->is-atom?
    29973     # TODO: check t->left == addr
    29974     # t = t->right
    29975 $addr-handle-array-payload-size:skip-addr:
    29976     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29977     # TODO: check eax != 0
    29978     # TODO: check !t->is-atom?
    29979     # TODO: check t->left == handle
    29980     # t = t->right
    29981 $addr-handle-array-payload-size:skip-handle:
    29982     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29983     # TODO: check eax != 0
    29984     # TODO: check !t->is-atom?
    29985     # TODO: check t->left == array
    29986     # t = t->right
    29987 $addr-handle-array-payload-size:skip-array:
    29988     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29989     # TODO: check eax != 0
    29990     # if !t->is-atom? t = t->left
    29991     81 7/subop/compare *eax 0/imm32/false
    29992     {
    29993       75/jump-if-!= break/disp8
    29994       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29995     }
    29996 $addr-handle-array-payload-size:compute-size:
    29997     # TODO: check t->is-atom?
    29998     # return size(t->value)
    29999     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30000 $addr-handle-array-payload-size:end:
    30001     # . epilogue
    30002     89/<- %esp 5/r32/ebp
    30003     5d/pop-to-ebp
    30004     c3/return
    30005
    30006 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30007     # . prologue
    30008     55/push-ebp
    30009     89/<- %ebp 4/r32/esp
    30010     # var t/eax: (addr type-tree) = s->value->type
    30011     8b/-> *(ebp+8) 0/r32/eax
    30012     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30013     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30014     # TODO: check eax != 0
    30015     # TODO: check !t->is-atom?
    30016     # TODO: check t->left == addr
    30017     # t = t->right
    30018 $addr-handle-stream-payload-size:skip-addr:
    30019     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30020     # TODO: check eax != 0
    30021     # TODO: check !t->is-atom?
    30022     # TODO: check t->left == handle
    30023     # t = t->right
    30024 $addr-handle-stream-payload-size:skip-handle:
    30025     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30026     # TODO: check eax != 0
    30027     # TODO: check !t->is-atom?
    30028     # TODO: check t->left == stream
    30029     # t = t->right
    30030 $addr-handle-stream-payload-size:skip-stream:
    30031     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30032     # TODO: check eax != 0
    30033     # if !t->is-atom? t = t->left
    30034     81 7/subop/compare *eax 0/imm32/false
    30035     {
    30036       75/jump-if-!= break/disp8
    30037       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30038     }
    30039 $addr-handle-stream-payload-size:compute-size:
    30040     # TODO: check t->is-atom?
    30041     # return size(t->value)
    30042     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30043 $addr-handle-stream-payload-size:end:
    30044     # . epilogue
    30045     89/<- %esp 5/r32/ebp
    30046     5d/pop-to-ebp
    30047     c3/return
    30048
    30049 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
    30050     # precondition: n is positive
    30051     # . prologue
    30052     55/push-ebp
    30053     89/<- %ebp 4/r32/esp
    30054     # eax = n
    30055     8b/-> *(ebp+8) 0/r32/eax
    30056     # if (n < 0) abort
    30057     3d/compare-eax-with 0/imm32
    30058     0f 8c/jump-if-< $power-of-2?:abort/disp32
    30059     # var tmp/eax: int = n-1
    30060     48/decrement-eax
    30061     # var tmp2/eax: int = n & tmp
    30062     23/and-> *(ebp+8) 0/r32/eax
    30063     # return (tmp2 == 0)
    30064     3d/compare-eax-and 0/imm32
    30065     0f 94/set-byte-if-= %al
    30066     81 4/subop/and %eax 0xff/imm32
    30067 $power-of-2?:end:
    30068     # . epilogue
    30069     89/<- %esp 5/r32/ebp
    30070     5d/pop-to-ebp
    30071     c3/return
    30072
    30073 $power-of-2?:abort:
    30074     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
    30075     (flush *(ebp+0xc))
    30076     (stop *(ebp+0x10) 1)
    30077     # never gets here
    30078
    30079 num-shift-rights:  # n: int -> result/eax: int
    30080     # precondition: n is a positive power of 2
    30081     # . prologue
    30082     55/push-ebp
    30083     89/<- %ebp 4/r32/esp
    30084     # . save registers
    30085     51/push-ecx
    30086     # var curr/ecx: int = n
    30087     8b/-> *(ebp+8) 1/r32/ecx
    30088     # result = 0
    30089     b8/copy-to-eax 0/imm32
    30090     {
    30091       # if (curr <= 1) break
    30092       81 7/subop/compare %ecx 1/imm32
    30093       7e/jump-if-<= break/disp8
    30094       40/increment-eax
    30095       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
    30096       eb/jump loop/disp8
    30097     }
    30098 $num-shift-rights:end:
    30099     # . restore registers
    30100     59/pop-to-ecx
    30101     # . epilogue
    30102     89/<- %esp 5/r32/ebp
    30103     5d/pop-to-ebp
    30104     c3/return
    30105
    30106 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
    30107     # . prologue
    30108     55/push-ebp
    30109     89/<- %ebp 4/r32/esp
    30110     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
    30111     8b/-> *(ebp+8) 0/r32/eax
    30112     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30113     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    30114     # var output-var/eax: (addr var) = second-inout->value
    30115     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30116 #?     (write-buffered Stderr "mu-get-offset: ")
    30117 #?     (write-int32-hex-buffered Stderr %eax)
    30118 #?     (write-buffered Stderr " name: ")
    30119 #?     50/push-eax
    30120 #?     (lookup *eax *(eax+4))  # Var-name
    30121 #?     (write-buffered Stderr %eax)
    30122 #?     58/pop-to-eax
    30123 #?     (write-buffered Stderr Newline)
    30124 #?     (flush Stderr)
    30125     # return output-var->stack-offset
    30126     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
    30127 #?     (write-buffered Stderr "=> ")
    30128 #?     (write-int32-hex-buffered Stderr %eax)
    30129 #?     (write-buffered Stderr Newline)
    30130 #?     (flush Stderr)
    30131 $emit-get-offset:end:
    30132     # . epilogue
    30133     89/<- %esp 5/r32/ebp
    30134     5d/pop-to-ebp
    30135     c3/return
    30136
    30137 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)
    30138     # . prologue
    30139     55/push-ebp
    30140     89/<- %ebp 4/r32/esp
    30141     # . save registers
    30142     50/push-eax
    30143     51/push-ecx
    30144     56/push-esi
    30145     # esi = block
    30146     8b/-> *(ebp+0xc) 6/r32/esi
    30147     # block->var->block-depth = *Curr-block-depth
    30148     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30149     8b/-> *Curr-block-depth 1/r32/ecx
    30150     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
    30151     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    30152     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30153     #
    30154     {
    30155 $emit-subx-block:check-empty:
    30156       3d/compare-eax-and 0/imm32
    30157       0f 84/jump-if-= break/disp32
    30158       (emit-indent *(ebp+8) *Curr-block-depth)
    30159       (write-buffered *(ebp+8) "{\n")
    30160       # var v/ecx: (addr var) = lookup(block->var)
    30161       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30162       89/<- %ecx 0/r32/eax
    30163       #
    30164       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30165       (write-buffered *(ebp+8) %eax)
    30166       (write-buffered *(ebp+8) ":loop:\n")
    30167       ff 0/subop/increment *Curr-block-depth
    30168       (push *(ebp+0x10) *(esi+0xc))  # Block-var
    30169       (push *(ebp+0x10) *(esi+0x10))  # Block-var
    30170       (push *(ebp+0x10) 0)  # false
    30171       # emit block->statements
    30172       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30173       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    30174       (pop *(ebp+0x10))  # => eax
    30175       (pop *(ebp+0x10))  # => eax
    30176       (pop *(ebp+0x10))  # => eax
    30177       ff 1/subop/decrement *Curr-block-depth
    30178       (emit-indent *(ebp+8) *Curr-block-depth)
    30179       (write-buffered *(ebp+8) "}\n")
    30180       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30181       (write-buffered *(ebp+8) %eax)
    30182       (write-buffered *(ebp+8) ":break:\n")
    30183     }
    30184 $emit-subx-block:end:
    30185     # . restore registers
    30186     5e/pop-to-esi
    30187     59/pop-to-ecx
    30188     58/pop-to-eax
    30189     # . epilogue
    30190     89/<- %esp 5/r32/ebp
    30191     5d/pop-to-ebp
    30192     c3/return
    30193
    30194 # Primitives supported
    30195 # See mu_instructions for a summary of this linked-list data structure.
    30196 #
    30197 # For each operation, put variants with hard-coded registers before flexible ones.
    30198 #
    30199 # Unfortunately, our restrictions on addresses require that various fields in
    30200 # primitives be handles, which complicates these definitions.
    30201 #   - we need to insert dummy fields all over the place for fake alloc-ids
    30202 #   - we can't use our syntax sugar of quoted literals for string fields
    30203 #
    30204 # Fake alloc-ids are needed because our type definitions up top require
    30205 # handles but it's clearer to statically allocate these long-lived objects.
    30206 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
    30207 #
    30208 # Every 'object' below starts with a fake alloc-id. It may also contain other
    30209 # fake alloc-ids for various handle fields.
    30210 #
    30211 # I think of objects starting with a fake alloc-id as having type 'payload'.
    30212 # It's not really intended to be created dynamically; for that use `allocate`
    30213 # as usual.
    30214 #
    30215 # Idea for a notation to simplify such definitions:
    30216 #   _Primitive-increment-eax:  # (payload primitive)
    30217 #     0x11/alloc-id:fake:payload
    30218 #     0x11 @(0x11 "increment")  # name
    30219 #     0 0                       # inouts
    30220 #     0x11 @(0x11/payload
    30221 #            0x11 @(0x11/payload  # List-value
    30222 #                   0 0             # Var-name
    30223 #                   0x11 @(0x11     # Var-type
    30224 #                          1/is-atom
    30225 #                          1/value 0/unused   # Type-tree-left
    30226 #                          0 0                # Type-tree-right
    30227 #                         )
    30228 #                   1               # block-depth
    30229 #                   0               # stack-offset
    30230 #                   0x11 @(0x11 "eax")  # Var-register
    30231 #                  )
    30232 #            0 0)                 # List-next
    30233 #     ...
    30234 #     _Primitive-increment-ecx/imm32/next
    30235 #   ...
    30236 # Awfully complex and non-obvious. But also clearly signals there's something
    30237 # to learn here, so may be worth trying.
    30238 #
    30239 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
    30240 #
    30241 # For now we'll continue to just use comments and manually ensure they stay up
    30242 # to date.
    30243 == data
    30244 Primitives:  # (addr primitive)
    30245 # - increment/decrement
    30246 _Primitive-increment-eax:  # (addr primitive)
    30247     # var/eax <- increment => 40/increment-eax
    30248     0x11/imm32/alloc-id:fake
    30249     _string-increment/imm32/name
    30250     0/imm32/no-inouts
    30251     0/imm32/no-inouts
    30252     0x11/imm32/alloc-id:fake
    30253     Single-int-var-in-eax/imm32/outputs
    30254     0x11/imm32/alloc-id:fake
    30255     _string_40_increment_eax/imm32/subx-name
    30256     0/imm32/no-rm32
    30257     0/imm32/no-r32
    30258     0/imm32/no-imm32
    30259     0/imm32/no-imm8
    30260     0/imm32/no-disp32
    30261     0/imm32/no-xm32
    30262     0/imm32/no-x32
    30263     0x11/imm32/alloc-id:fake
    30264     _Primitive-increment-ecx/imm32/next
    30265 _Primitive-increment-ecx:  # (payload primitive)
    30266     0x11/imm32/alloc-id:fake:payload
    30267     # var/ecx <- increment => 41/increment-ecx
    30268     0x11/imm32/alloc-id:fake
    30269     _string-increment/imm32/name
    30270     0/imm32/no-inouts
    30271     0/imm32/no-inouts
    30272     0x11/imm32/alloc-id:fake
    30273     Single-int-var-in-ecx/imm32/outputs
    30274     0x11/imm32/alloc-id:fake
    30275     _string_41_increment_ecx/imm32/subx-name
    30276     0/imm32/no-rm32
    30277     0/imm32/no-r32
    30278     0/imm32/no-imm32
    30279     0/imm32/no-imm8
    30280     0/imm32/no-disp32
    30281     0/imm32/no-xm32
    30282     0/imm32/no-x32
    30283     0x11/imm32/alloc-id:fake
    30284     _Primitive-increment-edx/imm32/next
    30285 _Primitive-increment-edx:  # (payload primitive)
    30286     0x11/imm32/alloc-id:fake:payload
    30287     # var/edx <- increment => 42/increment-edx
    30288     0x11/imm32/alloc-id:fake
    30289     _string-increment/imm32/name
    30290     0/imm32/no-inouts
    30291     0/imm32/no-inouts
    30292     0x11/imm32/alloc-id:fake
    30293     Single-int-var-in-edx/imm32/outputs
    30294     0x11/imm32/alloc-id:fake
    30295     _string_42_increment_edx/imm32/subx-name
    30296     0/imm32/no-rm32
    30297     0/imm32/no-r32
    30298     0/imm32/no-imm32
    30299     0/imm32/no-imm8
    30300     0/imm32/no-disp32
    30301     0/imm32/no-xm32
    30302     0/imm32/no-x32
    30303     0x11/imm32/alloc-id:fake
    30304     _Primitive-increment-ebx/imm32/next
    30305 _Primitive-increment-ebx:  # (payload primitive)
    30306     0x11/imm32/alloc-id:fake:payload
    30307     # var/ebx <- increment => 43/increment-ebx
    30308     0x11/imm32/alloc-id:fake
    30309     _string-increment/imm32/name
    30310     0/imm32/no-inouts
    30311     0/imm32/no-inouts
    30312     0x11/imm32/alloc-id:fake
    30313     Single-int-var-in-ebx/imm32/outputs
    30314     0x11/imm32/alloc-id:fake
    30315     _string_43_increment_ebx/imm32/subx-name
    30316     0/imm32/no-rm32
    30317     0/imm32/no-r32
    30318     0/imm32/no-imm32
    30319     0/imm32/no-imm8
    30320     0/imm32/no-disp32
    30321     0/imm32/no-xm32
    30322     0/imm32/no-x32
    30323     0x11/imm32/alloc-id:fake
    30324     _Primitive-increment-esi/imm32/next
    30325 _Primitive-increment-esi:  # (payload primitive)
    30326     0x11/imm32/alloc-id:fake:payload
    30327     # var/esi <- increment => 46/increment-esi
    30328     0x11/imm32/alloc-id:fake
    30329     _string-increment/imm32/name
    30330     0/imm32/no-inouts
    30331     0/imm32/no-inouts
    30332     0x11/imm32/alloc-id:fake
    30333     Single-int-var-in-esi/imm32/outputs
    30334     0x11/imm32/alloc-id:fake
    30335     _string_46_increment_esi/imm32/subx-name
    30336     0/imm32/no-rm32
    30337     0/imm32/no-r32
    30338     0/imm32/no-imm32
    30339     0/imm32/no-imm8
    30340     0/imm32/no-disp32
    30341     0/imm32/no-xm32
    30342     0/imm32/no-x32
    30343     0x11/imm32/alloc-id:fake
    30344     _Primitive-increment-edi/imm32/next
    30345 _Primitive-increment-edi:  # (payload primitive)
    30346     0x11/imm32/alloc-id:fake:payload
    30347     # var/edi <- increment => 47/increment-edi
    30348     0x11/imm32/alloc-id:fake
    30349     _string-increment/imm32/name
    30350     0/imm32/no-inouts
    30351     0/imm32/no-inouts
    30352     0x11/imm32/alloc-id:fake
    30353     Single-int-var-in-edi/imm32/outputs
    30354     0x11/imm32/alloc-id:fake
    30355     _string_47_increment_edi/imm32/subx-name
    30356     0/imm32/no-rm32
    30357     0/imm32/no-r32
    30358     0/imm32/no-imm32
    30359     0/imm32/no-imm8
    30360     0/imm32/no-disp32
    30361     0/imm32/no-xm32
    30362     0/imm32/no-x32
    30363     0x11/imm32/alloc-id:fake
    30364     _Primitive-decrement-eax/imm32/next
    30365 _Primitive-decrement-eax:  # (payload primitive)
    30366     0x11/imm32/alloc-id:fake:payload
    30367     # var/eax <- decrement => 48/decrement-eax
    30368     0x11/imm32/alloc-id:fake
    30369     _string-decrement/imm32/name
    30370     0/imm32/no-inouts
    30371     0/imm32/no-inouts
    30372     0x11/imm32/alloc-id:fake
    30373     Single-int-var-in-eax/imm32/outputs
    30374     0x11/imm32/alloc-id:fake
    30375     _string_48_decrement_eax/imm32/subx-name
    30376     0/imm32/no-rm32
    30377     0/imm32/no-r32
    30378     0/imm32/no-imm32
    30379     0/imm32/no-imm8
    30380     0/imm32/no-disp32
    30381     0/imm32/no-xm32
    30382     0/imm32/no-x32
    30383     0x11/imm32/alloc-id:fake
    30384     _Primitive-decrement-ecx/imm32/next
    30385 _Primitive-decrement-ecx:  # (payload primitive)
    30386     0x11/imm32/alloc-id:fake:payload
    30387     # var/ecx <- decrement => 49/decrement-ecx
    30388     0x11/imm32/alloc-id:fake
    30389     _string-decrement/imm32/name
    30390     0/imm32/no-inouts
    30391     0/imm32/no-inouts
    30392     0x11/imm32/alloc-id:fake
    30393     Single-int-var-in-ecx/imm32/outputs
    30394     0x11/imm32/alloc-id:fake
    30395     _string_49_decrement_ecx/imm32/subx-name
    30396     0/imm32/no-rm32
    30397     0/imm32/no-r32
    30398     0/imm32/no-imm32
    30399     0/imm32/no-imm8
    30400     0/imm32/no-disp32
    30401     0/imm32/no-xm32
    30402     0/imm32/no-x32
    30403     0x11/imm32/alloc-id:fake
    30404     _Primitive-decrement-edx/imm32/next
    30405 _Primitive-decrement-edx:  # (payload primitive)
    30406     0x11/imm32/alloc-id:fake:payload
    30407     # var/edx <- decrement => 4a/decrement-edx
    30408     0x11/imm32/alloc-id:fake
    30409     _string-decrement/imm32/name
    30410     0/imm32/no-inouts
    30411     0/imm32/no-inouts
    30412     0x11/imm32/alloc-id:fake
    30413     Single-int-var-in-edx/imm32/outputs
    30414     0x11/imm32/alloc-id:fake
    30415     _string_4a_decrement_edx/imm32/subx-name
    30416     0/imm32/no-rm32
    30417     0/imm32/no-r32
    30418     0/imm32/no-imm32
    30419     0/imm32/no-imm8
    30420     0/imm32/no-disp32
    30421     0/imm32/no-xm32
    30422     0/imm32/no-x32
    30423     0x11/imm32/alloc-id:fake
    30424     _Primitive-decrement-ebx/imm32/next
    30425 _Primitive-decrement-ebx:  # (payload primitive)
    30426     0x11/imm32/alloc-id:fake:payload
    30427     # var/ebx <- decrement => 4b/decrement-ebx
    30428     0x11/imm32/alloc-id:fake
    30429     _string-decrement/imm32/name
    30430     0/imm32/no-inouts
    30431     0/imm32/no-inouts
    30432     0x11/imm32/alloc-id:fake
    30433     Single-int-var-in-ebx/imm32/outputs
    30434     0x11/imm32/alloc-id:fake
    30435     _string_4b_decrement_ebx/imm32/subx-name
    30436     0/imm32/no-rm32
    30437     0/imm32/no-r32
    30438     0/imm32/no-imm32
    30439     0/imm32/no-imm8
    30440     0/imm32/no-disp32
    30441     0/imm32/no-xm32
    30442     0/imm32/no-x32
    30443     0x11/imm32/alloc-id:fake
    30444     _Primitive-decrement-esi/imm32/next
    30445 _Primitive-decrement-esi:  # (payload primitive)
    30446     0x11/imm32/alloc-id:fake:payload
    30447     # var/esi <- decrement => 4e/decrement-esi
    30448     0x11/imm32/alloc-id:fake
    30449     _string-decrement/imm32/name
    30450     0/imm32/no-inouts
    30451     0/imm32/no-inouts
    30452     0x11/imm32/alloc-id:fake
    30453     Single-int-var-in-esi/imm32/outputs
    30454     0x11/imm32/alloc-id:fake
    30455     _string_4e_decrement_esi/imm32/subx-name
    30456     0/imm32/no-rm32
    30457     0/imm32/no-r32
    30458     0/imm32/no-imm32
    30459     0/imm32/no-imm8
    30460     0/imm32/no-disp32
    30461     0/imm32/no-xm32
    30462     0/imm32/no-x32
    30463     0x11/imm32/alloc-id:fake
    30464     _Primitive-decrement-edi/imm32/next
    30465 _Primitive-decrement-edi:  # (payload primitive)
    30466     0x11/imm32/alloc-id:fake:payload
    30467     # var/edi <- decrement => 4f/decrement-edi
    30468     0x11/imm32/alloc-id:fake
    30469     _string-decrement/imm32/name
    30470     0/imm32/no-inouts
    30471     0/imm32/no-inouts
    30472     0x11/imm32/alloc-id:fake
    30473     Single-int-var-in-edi/imm32/outputs
    30474     0x11/imm32/alloc-id:fake
    30475     _string_4f_decrement_edi/imm32/subx-name
    30476     0/imm32/no-rm32
    30477     0/imm32/no-r32
    30478     0/imm32/no-imm32
    30479     0/imm32/no-imm8
    30480     0/imm32/no-disp32
    30481     0/imm32/no-xm32
    30482     0/imm32/no-x32
    30483     0x11/imm32/alloc-id:fake
    30484     _Primitive-increment-mem/imm32/next
    30485 _Primitive-increment-mem:  # (payload primitive)
    30486     0x11/imm32/alloc-id:fake:payload
    30487     # increment var => ff 0/subop/increment *(ebp+__)
    30488     0x11/imm32/alloc-id:fake
    30489     _string-increment/imm32/name
    30490     0x11/imm32/alloc-id:fake
    30491     Single-int-var-in-mem/imm32/inouts
    30492     0/imm32/no-outputs
    30493     0/imm32/no-outputs
    30494     0x11/imm32/alloc-id:fake
    30495     _string_ff_subop_increment/imm32/subx-name
    30496     1/imm32/rm32-is-first-inout
    30497     0/imm32/no-r32
    30498     0/imm32/no-imm32
    30499     0/imm32/no-imm8
    30500     0/imm32/no-disp32
    30501     0/imm32/no-xm32
    30502     0/imm32/no-x32
    30503     0x11/imm32/alloc-id:fake
    30504     _Primitive-increment-reg/imm32/next
    30505 _Primitive-increment-reg:  # (payload primitive)
    30506     0x11/imm32/alloc-id:fake:payload
    30507     # var/reg <- increment => ff 0/subop/increment %__
    30508     0x11/imm32/alloc-id:fake
    30509     _string-increment/imm32/name
    30510     0/imm32/no-inouts
    30511     0/imm32/no-inouts
    30512     0x11/imm32/alloc-id:fake
    30513     Single-int-var-in-some-register/imm32/outputs
    30514     0x11/imm32/alloc-id:fake
    30515     _string_ff_subop_increment/imm32/subx-name
    30516     3/imm32/rm32-is-first-output
    30517     0/imm32/no-r32
    30518     0/imm32/no-imm32
    30519     0/imm32/no-imm8
    30520     0/imm32/no-disp32
    30521     0/imm32/no-xm32
    30522     0/imm32/no-x32
    30523     0x11/imm32/alloc-id:fake
    30524     _Primitive-decrement-mem/imm32/next
    30525 _Primitive-decrement-mem:  # (payload primitive)
    30526     0x11/imm32/alloc-id:fake:payload
    30527     # decrement var => ff 1/subop/decrement *(ebp+__)
    30528     0x11/imm32/alloc-id:fake
    30529     _string-decrement/imm32/name
    30530     0x11/imm32/alloc-id:fake
    30531     Single-int-var-in-mem/imm32/inouts
    30532     0/imm32/no-outputs
    30533     0/imm32/no-outputs
    30534     0x11/imm32/alloc-id:fake
    30535     _string_ff_subop_decrement/imm32/subx-name
    30536     1/imm32/rm32-is-first-inout
    30537     0/imm32/no-r32
    30538     0/imm32/no-imm32
    30539     0/imm32/no-imm8
    30540     0/imm32/no-disp32
    30541     0/imm32/no-xm32
    30542     0/imm32/no-x32
    30543     0x11/imm32/alloc-id:fake
    30544     _Primitive-decrement-reg/imm32/next
    30545 _Primitive-decrement-reg:  # (payload primitive)
    30546     0x11/imm32/alloc-id:fake:payload
    30547     # var/reg <- decrement => ff 1/subop/decrement %__
    30548     0x11/imm32/alloc-id:fake
    30549     _string-decrement/imm32/name
    30550     0/imm32/no-inouts
    30551     0/imm32/no-inouts
    30552     0x11/imm32/alloc-id:fake
    30553     Single-int-var-in-some-register/imm32/outputs
    30554     0x11/imm32/alloc-id:fake
    30555     _string_ff_subop_decrement/imm32/subx-name
    30556     3/imm32/rm32-is-first-output
    30557     0/imm32/no-r32
    30558     0/imm32/no-imm32
    30559     0/imm32/no-imm8
    30560     0/imm32/no-disp32
    30561     0/imm32/no-xm32
    30562     0/imm32/no-x32
    30563     0x11/imm32/alloc-id:fake
    30564     _Primitive-add-to-eax/imm32/next
    30565 # - add
    30566 _Primitive-add-to-eax:  # (payload primitive)
    30567     0x11/imm32/alloc-id:fake:payload
    30568     # var/eax <- add lit => 05/add-to-eax lit/imm32
    30569     0x11/imm32/alloc-id:fake
    30570     _string-add/imm32/name
    30571     0x11/imm32/alloc-id:fake
    30572     Single-lit-var/imm32/inouts
    30573     0x11/imm32/alloc-id:fake
    30574     Single-int-var-in-eax/imm32/outputs
    30575     0x11/imm32/alloc-id:fake
    30576     _string_05_add_to_eax/imm32/subx-name
    30577     0/imm32/no-rm32
    30578     0/imm32/no-r32
    30579     1/imm32/imm32-is-first-inout
    30580     0/imm32/no-imm8
    30581     0/imm32/no-disp32
    30582     0/imm32/no-xm32
    30583     0/imm32/no-x32
    30584     0x11/imm32/alloc-id:fake
    30585     _Primitive-add-reg-to-reg/imm32/next
    30586 _Primitive-add-reg-to-reg:  # (payload primitive)
    30587     0x11/imm32/alloc-id:fake:payload
    30588     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
    30589     0x11/imm32/alloc-id:fake
    30590     _string-add/imm32/name
    30591     0x11/imm32/alloc-id:fake
    30592     Single-int-var-in-some-register/imm32/inouts
    30593     0x11/imm32/alloc-id:fake
    30594     Single-int-var-in-some-register/imm32/outputs
    30595     0x11/imm32/alloc-id:fake
    30596     _string_01_add_to/imm32/subx-name
    30597     3/imm32/rm32-is-first-output
    30598     1/imm32/r32-is-first-inout
    30599     0/imm32/no-imm32
    30600     0/imm32/no-imm8
    30601     0/imm32/no-disp32
    30602     0/imm32/no-xm32
    30603     0/imm32/no-x32
    30604     0x11/imm32/alloc-id:fake
    30605     _Primitive-add-reg-to-mem/imm32/next
    30606 _Primitive-add-reg-to-mem:  # (payload primitive)
    30607     0x11/imm32/alloc-id:fake:payload
    30608     # add-to var1 var2/reg => 01/add-to var1 var2/r32
    30609     0x11/imm32/alloc-id:fake
    30610     _string-add-to/imm32/name
    30611     0x11/imm32/alloc-id:fake
    30612     Two-args-int-stack-int-reg/imm32/inouts
    30613     0/imm32/no-outputs
    30614     0/imm32/no-outputs
    30615     0x11/imm32/alloc-id:fake
    30616     _string_01_add_to/imm32/subx-name
    30617     1/imm32/rm32-is-first-inout
    30618     2/imm32/r32-is-second-inout
    30619     0/imm32/no-imm32
    30620     0/imm32/no-imm8
    30621     0/imm32/no-disp32
    30622     0/imm32/no-xm32
    30623     0/imm32/no-x32
    30624     0x11/imm32/alloc-id:fake
    30625     _Primitive-add-mem-to-reg/imm32/next
    30626 _Primitive-add-mem-to-reg:  # (payload primitive)
    30627     0x11/imm32/alloc-id:fake:payload
    30628     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
    30629     0x11/imm32/alloc-id:fake
    30630     _string-add/imm32/name
    30631     0x11/imm32/alloc-id:fake
    30632     Single-int-var-in-mem/imm32/inouts
    30633     0x11/imm32/alloc-id:fake
    30634     Single-int-var-in-some-register/imm32/outputs
    30635     0x11/imm32/alloc-id:fake
    30636     _string_03_add/imm32/subx-name
    30637     1/imm32/rm32-is-first-inout
    30638     3/imm32/r32-is-first-output
    30639     0/imm32/no-imm32
    30640     0/imm32/no-imm8
    30641     0/imm32/no-disp32
    30642     0/imm32/no-xm32
    30643     0/imm32/no-x32
    30644     0x11/imm32/alloc-id:fake
    30645     _Primitive-add-lit-to-reg/imm32/next
    30646 _Primitive-add-lit-to-reg:  # (payload primitive)
    30647     0x11/imm32/alloc-id:fake:payload
    30648     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
    30649     0x11/imm32/alloc-id:fake
    30650     _string-add/imm32/name
    30651     0x11/imm32/alloc-id:fake
    30652     Single-lit-var/imm32/inouts
    30653     0x11/imm32/alloc-id:fake
    30654     Single-int-var-in-some-register/imm32/outputs
    30655     0x11/imm32/alloc-id:fake
    30656     _string_81_subop_add/imm32/subx-name
    30657     3/imm32/rm32-is-first-output
    30658     0/imm32/no-r32
    30659     1/imm32/imm32-is-first-inout
    30660     0/imm32/no-imm8
    30661     0/imm32/no-disp32
    30662     0/imm32/no-xm32
    30663     0/imm32/no-x32
    30664     0x11/imm32/alloc-id:fake
    30665     _Primitive-add-lit-to-mem/imm32/next
    30666 _Primitive-add-lit-to-mem:  # (payload primitive)
    30667     0x11/imm32/alloc-id:fake:payload
    30668     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
    30669     0x11/imm32/alloc-id:fake
    30670     _string-add-to/imm32/name
    30671     0x11/imm32/alloc-id:fake
    30672     Int-var-and-literal/imm32/inouts
    30673     0/imm32/no-outputs
    30674     0/imm32/no-outputs
    30675     0x11/imm32/alloc-id:fake
    30676     _string_81_subop_add/imm32/subx-name
    30677     1/imm32/rm32-is-first-inout
    30678     0/imm32/no-r32
    30679     2/imm32/imm32-is-second-inout
    30680     0/imm32/no-imm8
    30681     0/imm32/no-disp32
    30682     0/imm32/no-xm32
    30683     0/imm32/no-x32
    30684     0x11/imm32/alloc-id:fake
    30685     _Primitive-subtract-from-eax/imm32/next
    30686 # - subtract
    30687 _Primitive-subtract-from-eax:  # (payload primitive)
    30688     0x11/imm32/alloc-id:fake:payload
    30689     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
    30690     0x11/imm32/alloc-id:fake
    30691     _string-subtract/imm32/name
    30692     0x11/imm32/alloc-id:fake
    30693     Single-lit-var/imm32/inouts
    30694     0x11/imm32/alloc-id:fake
    30695     Single-int-var-in-eax/imm32/outputs
    30696     0x11/imm32/alloc-id:fake
    30697     _string_2d_subtract_from_eax/imm32/subx-name
    30698     0/imm32/no-rm32
    30699     0/imm32/no-r32
    30700     1/imm32/imm32-is-first-inout
    30701     0/imm32/no-imm8
    30702     0/imm32/no-disp32
    30703     0/imm32/no-xm32
    30704     0/imm32/no-x32
    30705     0x11/imm32/alloc-id:fake
    30706     _Primitive-subtract-reg-from-reg/imm32/next
    30707 _Primitive-subtract-reg-from-reg:  # (payload primitive)
    30708     0x11/imm32/alloc-id:fake:payload
    30709     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
    30710     0x11/imm32/alloc-id:fake
    30711     _string-subtract/imm32/name
    30712     0x11/imm32/alloc-id:fake
    30713     Single-int-var-in-some-register/imm32/inouts
    30714     0x11/imm32/alloc-id:fake
    30715     Single-int-var-in-some-register/imm32/outputs
    30716     0x11/imm32/alloc-id:fake
    30717     _string_29_subtract_from/imm32/subx-name
    30718     3/imm32/rm32-is-first-output
    30719     1/imm32/r32-is-first-inout
    30720     0/imm32/no-imm32
    30721     0/imm32/no-imm8
    30722     0/imm32/no-disp32
    30723     0/imm32/no-xm32
    30724     0/imm32/no-x32
    30725     0x11/imm32/alloc-id:fake
    30726     _Primitive-subtract-reg-from-mem/imm32/next
    30727 _Primitive-subtract-reg-from-mem:  # (payload primitive)
    30728     0x11/imm32/alloc-id:fake:payload
    30729     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
    30730     0x11/imm32/alloc-id:fake
    30731     _string-subtract-from/imm32/name
    30732     0x11/imm32/alloc-id:fake
    30733     Two-args-int-stack-int-reg/imm32/inouts
    30734     0/imm32/no-outputs
    30735     0/imm32/no-outputs
    30736     0x11/imm32/alloc-id:fake
    30737     _string_29_subtract_from/imm32/subx-name
    30738     1/imm32/rm32-is-first-inout
    30739     2/imm32/r32-is-second-inout
    30740     0/imm32/no-imm32
    30741     0/imm32/no-imm8
    30742     0/imm32/no-disp32
    30743     0/imm32/no-xm32
    30744     0/imm32/no-x32
    30745     0x11/imm32/alloc-id:fake
    30746     _Primitive-subtract-mem-from-reg/imm32/next
    30747 _Primitive-subtract-mem-from-reg:  # (payload primitive)
    30748     0x11/imm32/alloc-id:fake:payload
    30749     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
    30750     0x11/imm32/alloc-id:fake
    30751     _string-subtract/imm32/name
    30752     0x11/imm32/alloc-id:fake
    30753     Single-int-var-in-mem/imm32/inouts
    30754     0x11/imm32/alloc-id:fake
    30755     Single-int-var-in-some-register/imm32/outputs
    30756     0x11/imm32/alloc-id:fake
    30757     _string_2b_subtract/imm32/subx-name
    30758     1/imm32/rm32-is-first-inout
    30759     3/imm32/r32-is-first-output
    30760     0/imm32/no-imm32
    30761     0/imm32/no-imm8
    30762     0/imm32/no-disp32
    30763     0/imm32/no-xm32
    30764     0/imm32/no-x32
    30765     0x11/imm32/alloc-id:fake
    30766     _Primitive-subtract-lit-from-reg/imm32/next
    30767 _Primitive-subtract-lit-from-reg:  # (payload primitive)
    30768     0x11/imm32/alloc-id:fake:payload
    30769     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30770     0x11/imm32/alloc-id:fake
    30771     _string-subtract/imm32/name
    30772     0x11/imm32/alloc-id:fake
    30773     Single-lit-var/imm32/inouts
    30774     0x11/imm32/alloc-id:fake
    30775     Single-int-var-in-some-register/imm32/outputs
    30776     0x11/imm32/alloc-id:fake
    30777     _string_81_subop_subtract/imm32/subx-name
    30778     3/imm32/rm32-is-first-output
    30779     0/imm32/no-r32
    30780     1/imm32/imm32-is-first-inout
    30781     0/imm32/no-imm8
    30782     0/imm32/no-disp32
    30783     0/imm32/no-xm32
    30784     0/imm32/no-x32
    30785     0x11/imm32/alloc-id:fake
    30786     _Primitive-subtract-lit-from-mem/imm32/next
    30787 _Primitive-subtract-lit-from-mem:  # (payload primitive)
    30788     0x11/imm32/alloc-id:fake:payload
    30789     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30790     0x11/imm32/alloc-id:fake
    30791     _string-subtract-from/imm32/name
    30792     0x11/imm32/alloc-id:fake
    30793     Int-var-and-literal/imm32/inouts
    30794     0/imm32/no-outputs
    30795     0/imm32/no-outputs
    30796     0x11/imm32/alloc-id:fake
    30797     _string_81_subop_subtract/imm32/subx-name
    30798     1/imm32/rm32-is-first-inout
    30799     0/imm32/no-r32
    30800     2/imm32/imm32-is-second-inout
    30801     0/imm32/no-imm8
    30802     0/imm32/no-disp32
    30803     0/imm32/no-xm32
    30804     0/imm32/no-x32
    30805     0x11/imm32/alloc-id:fake
    30806     _Primitive-and-with-eax/imm32/next
    30807 # - and
    30808 _Primitive-and-with-eax:  # (payload primitive)
    30809     0x11/imm32/alloc-id:fake:payload
    30810     # var/eax <- and lit => 25/and-with-eax lit/imm32
    30811     0x11/imm32/alloc-id:fake
    30812     _string-and/imm32/name
    30813     0x11/imm32/alloc-id:fake
    30814     Single-lit-var/imm32/inouts
    30815     0x11/imm32/alloc-id:fake
    30816     Single-int-var-in-eax/imm32/outputs
    30817     0x11/imm32/alloc-id:fake
    30818     _string_25_and_with_eax/imm32/subx-name
    30819     0/imm32/no-rm32
    30820     0/imm32/no-r32
    30821     1/imm32/imm32-is-first-inout
    30822     0/imm32/no-imm8
    30823     0/imm32/no-disp32
    30824     0/imm32/no-xm32
    30825     0/imm32/no-x32
    30826     0x11/imm32/alloc-id:fake
    30827     _Primitive-and-reg-with-reg/imm32/next
    30828 _Primitive-and-reg-with-reg:  # (payload primitive)
    30829     0x11/imm32/alloc-id:fake:payload
    30830     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
    30831     0x11/imm32/alloc-id:fake
    30832     _string-and/imm32/name
    30833     0x11/imm32/alloc-id:fake
    30834     Single-int-var-in-some-register/imm32/inouts
    30835     0x11/imm32/alloc-id:fake
    30836     Single-int-var-in-some-register/imm32/outputs
    30837     0x11/imm32/alloc-id:fake
    30838     _string_21_and_with/imm32/subx-name
    30839     3/imm32/rm32-is-first-output
    30840     1/imm32/r32-is-first-inout
    30841     0/imm32/no-imm32
    30842     0/imm32/no-imm8
    30843     0/imm32/no-disp32
    30844     0/imm32/no-xm32
    30845     0/imm32/no-x32
    30846     0x11/imm32/alloc-id:fake
    30847     _Primitive-and-reg-with-mem/imm32/next
    30848 _Primitive-and-reg-with-mem:  # (payload primitive)
    30849     0x11/imm32/alloc-id:fake:payload
    30850     # and-with var1 var2/reg => 21/and-with var1 var2/r32
    30851     0x11/imm32/alloc-id:fake
    30852     _string-and-with/imm32/name
    30853     0x11/imm32/alloc-id:fake
    30854     Two-args-int-stack-int-reg/imm32/inouts
    30855     0/imm32/no-outputs
    30856     0/imm32/no-outputs
    30857     0x11/imm32/alloc-id:fake
    30858     _string_21_and_with/imm32/subx-name
    30859     1/imm32/rm32-is-first-inout
    30860     2/imm32/r32-is-second-inout
    30861     0/imm32/no-imm32
    30862     0/imm32/no-imm8
    30863     0/imm32/no-disp32
    30864     0/imm32/no-xm32
    30865     0/imm32/no-x32
    30866     0x11/imm32/alloc-id:fake
    30867     _Primitive-and-mem-with-reg/imm32/next
    30868 _Primitive-and-mem-with-reg:  # (payload primitive)
    30869     0x11/imm32/alloc-id:fake:payload
    30870     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
    30871     0x11/imm32/alloc-id:fake
    30872     _string-and/imm32/name
    30873     0x11/imm32/alloc-id:fake
    30874     Single-int-var-in-mem/imm32/inouts
    30875     0x11/imm32/alloc-id:fake
    30876     Single-int-var-in-some-register/imm32/outputs
    30877     0x11/imm32/alloc-id:fake
    30878     _string_23_and/imm32/subx-name
    30879     1/imm32/rm32-is-first-inout
    30880     3/imm32/r32-is-first-output
    30881     0/imm32/no-imm32
    30882     0/imm32/no-imm8
    30883     0/imm32/no-disp32
    30884     0/imm32/no-xm32
    30885     0/imm32/no-x32
    30886     0x11/imm32/alloc-id:fake
    30887     _Primitive-and-lit-with-reg/imm32/next
    30888 _Primitive-and-lit-with-reg:  # (payload primitive)
    30889     0x11/imm32/alloc-id:fake:payload
    30890     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
    30891     0x11/imm32/alloc-id:fake
    30892     _string-and/imm32/name
    30893     0x11/imm32/alloc-id:fake
    30894     Single-lit-var/imm32/inouts
    30895     0x11/imm32/alloc-id:fake
    30896     Single-int-var-in-some-register/imm32/outputs
    30897     0x11/imm32/alloc-id:fake
    30898     _string_81_subop_and/imm32/subx-name
    30899     3/imm32/rm32-is-first-output
    30900     0/imm32/no-r32
    30901     1/imm32/imm32-is-first-inout
    30902     0/imm32/no-imm8
    30903     0/imm32/no-disp32
    30904     0/imm32/no-xm32
    30905     0/imm32/no-x32
    30906     0x11/imm32/alloc-id:fake
    30907     _Primitive-and-lit-with-mem/imm32/next
    30908 _Primitive-and-lit-with-mem:  # (payload primitive)
    30909     0x11/imm32/alloc-id:fake:payload
    30910     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
    30911     0x11/imm32/alloc-id:fake
    30912     _string-and-with/imm32/name
    30913     0x11/imm32/alloc-id:fake
    30914     Int-var-and-literal/imm32/inouts
    30915     0/imm32/no-outputs
    30916     0/imm32/no-outputs
    30917     0x11/imm32/alloc-id:fake
    30918     _string_81_subop_and/imm32/subx-name
    30919     1/imm32/rm32-is-first-inout
    30920     0/imm32/no-r32
    30921     2/imm32/imm32-is-second-inout
    30922     0/imm32/no-imm8
    30923     0/imm32/no-disp32
    30924     0/imm32/no-xm32
    30925     0/imm32/no-x32
    30926     0x11/imm32/alloc-id:fake
    30927     _Primitive-or-with-eax/imm32/next
    30928 # - or
    30929 _Primitive-or-with-eax:  # (payload primitive)
    30930     0x11/imm32/alloc-id:fake:payload
    30931     # var/eax <- or lit => 0d/or-with-eax lit/imm32
    30932     0x11/imm32/alloc-id:fake
    30933     _string-or/imm32/name
    30934     0x11/imm32/alloc-id:fake
    30935     Single-lit-var/imm32/inouts
    30936     0x11/imm32/alloc-id:fake
    30937     Single-int-var-in-eax/imm32/outputs
    30938     0x11/imm32/alloc-id:fake
    30939     _string_0d_or_with_eax/imm32/subx-name
    30940     0/imm32/no-rm32
    30941     0/imm32/no-r32
    30942     1/imm32/imm32-is-first-inout
    30943     0/imm32/no-imm8
    30944     0/imm32/no-disp32
    30945     0/imm32/no-xm32
    30946     0/imm32/no-x32
    30947     0x11/imm32/alloc-id:fake
    30948     _Primitive-or-reg-with-reg/imm32/next
    30949 _Primitive-or-reg-with-reg:  # (payload primitive)
    30950     0x11/imm32/alloc-id:fake:payload
    30951     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
    30952     0x11/imm32/alloc-id:fake
    30953     _string-or/imm32/name
    30954     0x11/imm32/alloc-id:fake
    30955     Single-int-var-in-some-register/imm32/inouts
    30956     0x11/imm32/alloc-id:fake
    30957     Single-int-var-in-some-register/imm32/outputs
    30958     0x11/imm32/alloc-id:fake
    30959     _string_09_or_with/imm32/subx-name
    30960     3/imm32/rm32-is-first-output
    30961     1/imm32/r32-is-first-inout
    30962     0/imm32/no-imm32
    30963     0/imm32/no-imm8
    30964     0/imm32/no-disp32
    30965     0/imm32/no-xm32
    30966     0/imm32/no-x32
    30967     0x11/imm32/alloc-id:fake
    30968     _Primitive-or-reg-with-mem/imm32/next
    30969 _Primitive-or-reg-with-mem:  # (payload primitive)
    30970     0x11/imm32/alloc-id:fake:payload
    30971     # or-with var1 var2/reg => 09/or-with var1 var2/r32
    30972     0x11/imm32/alloc-id:fake
    30973     _string-or-with/imm32/name
    30974     0x11/imm32/alloc-id:fake
    30975     Two-args-int-stack-int-reg/imm32/inouts
    30976     0/imm32/no-outputs
    30977     0/imm32/no-outputs
    30978     0x11/imm32/alloc-id:fake
    30979     _string_09_or_with/imm32/subx-name
    30980     1/imm32/rm32-is-first-inout
    30981     2/imm32/r32-is-second-inout
    30982     0/imm32/no-imm32
    30983     0/imm32/no-imm8
    30984     0/imm32/no-disp32
    30985     0/imm32/no-xm32
    30986     0/imm32/no-x32
    30987     0x11/imm32/alloc-id:fake
    30988     _Primitive-or-mem-with-reg/imm32/next
    30989 _Primitive-or-mem-with-reg:  # (payload primitive)
    30990     0x11/imm32/alloc-id:fake:payload
    30991     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
    30992     0x11/imm32/alloc-id:fake
    30993     _string-or/imm32/name
    30994     0x11/imm32/alloc-id:fake
    30995     Single-int-var-in-mem/imm32/inouts
    30996     0x11/imm32/alloc-id:fake
    30997     Single-int-var-in-some-register/imm32/outputs
    30998     0x11/imm32/alloc-id:fake
    30999     _string_0b_or/imm32/subx-name
    31000     1/imm32/rm32-is-first-inout
    31001     3/imm32/r32-is-first-output
    31002     0/imm32/no-imm32
    31003     0/imm32/no-imm8
    31004     0/imm32/no-disp32
    31005     0/imm32/no-xm32
    31006     0/imm32/no-x32
    31007     0x11/imm32/alloc-id:fake
    31008     _Primitive-or-lit-with-reg/imm32/next
    31009 _Primitive-or-lit-with-reg:  # (payload primitive)
    31010     0x11/imm32/alloc-id:fake:payload
    31011     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
    31012     0x11/imm32/alloc-id:fake
    31013     _string-or/imm32/name
    31014     0x11/imm32/alloc-id:fake
    31015     Single-lit-var/imm32/inouts
    31016     0x11/imm32/alloc-id:fake
    31017     Single-int-var-in-some-register/imm32/outputs
    31018     0x11/imm32/alloc-id:fake
    31019     _string_81_subop_or/imm32/subx-name
    31020     3/imm32/rm32-is-first-output
    31021     0/imm32/no-r32
    31022     1/imm32/imm32-is-first-inout
    31023     0/imm32/no-imm8
    31024     0/imm32/no-disp32
    31025     0/imm32/no-xm32
    31026     0/imm32/no-x32
    31027     0x11/imm32/alloc-id:fake
    31028     _Primitive-or-lit-with-mem/imm32/next
    31029 _Primitive-or-lit-with-mem:  # (payload primitive)
    31030     0x11/imm32/alloc-id:fake:payload
    31031     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
    31032     0x11/imm32/alloc-id:fake
    31033     _string-or-with/imm32/name
    31034     0x11/imm32/alloc-id:fake
    31035     Int-var-and-literal/imm32/inouts
    31036     0/imm32/no-outputs
    31037     0/imm32/no-outputs
    31038     0x11/imm32/alloc-id:fake
    31039     _string_81_subop_or/imm32/subx-name
    31040     1/imm32/rm32-is-first-inout
    31041     0/imm32/no-r32
    31042     2/imm32/imm32-is-second-inout
    31043     0/imm32/no-imm8
    31044     0/imm32/no-disp32
    31045     0/imm32/no-xm32
    31046     0/imm32/no-x32
    31047     0x11/imm32/alloc-id:fake
    31048     _Primitive-xor-with-eax/imm32/next
    31049 # - xor
    31050 _Primitive-xor-with-eax:  # (payload primitive)
    31051     0x11/imm32/alloc-id:fake:payload
    31052     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
    31053     0x11/imm32/alloc-id:fake
    31054     _string-xor/imm32/name
    31055     0x11/imm32/alloc-id:fake
    31056     Single-lit-var/imm32/inouts
    31057     0x11/imm32/alloc-id:fake
    31058     Single-int-var-in-eax/imm32/outputs
    31059     0x11/imm32/alloc-id:fake
    31060     _string_35_xor_with_eax/imm32/subx-name
    31061     0/imm32/no-rm32
    31062     0/imm32/no-r32
    31063     1/imm32/imm32-is-first-inout
    31064     0/imm32/no-imm8
    31065     0/imm32/no-disp32
    31066     0/imm32/no-xm32
    31067     0/imm32/no-x32
    31068     0x11/imm32/alloc-id:fake
    31069     _Primitive-xor-reg-with-reg/imm32/next
    31070 _Primitive-xor-reg-with-reg:  # (payload primitive)
    31071     0x11/imm32/alloc-id:fake:payload
    31072     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
    31073     0x11/imm32/alloc-id:fake
    31074     _string-xor/imm32/name
    31075     0x11/imm32/alloc-id:fake
    31076     Single-int-var-in-some-register/imm32/inouts
    31077     0x11/imm32/alloc-id:fake
    31078     Single-int-var-in-some-register/imm32/outputs
    31079     0x11/imm32/alloc-id:fake
    31080     _string_31_xor_with/imm32/subx-name
    31081     3/imm32/rm32-is-first-output
    31082     1/imm32/r32-is-first-inout
    31083     0/imm32/no-imm32
    31084     0/imm32/no-imm8
    31085     0/imm32/no-disp32
    31086     0/imm32/no-xm32
    31087     0/imm32/no-x32
    31088     0x11/imm32/alloc-id:fake
    31089     _Primitive-xor-reg-with-mem/imm32/next
    31090 _Primitive-xor-reg-with-mem:  # (payload primitive)
    31091     0x11/imm32/alloc-id:fake:payload
    31092     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
    31093     0x11/imm32/alloc-id:fake
    31094     _string-xor-with/imm32/name
    31095     0x11/imm32/alloc-id:fake
    31096     Two-args-int-stack-int-reg/imm32/inouts
    31097     0/imm32/no-outputs
    31098     0/imm32/no-outputs
    31099     0x11/imm32/alloc-id:fake
    31100     _string_31_xor_with/imm32/subx-name
    31101     1/imm32/rm32-is-first-inout
    31102     2/imm32/r32-is-second-inout
    31103     0/imm32/no-imm32
    31104     0/imm32/no-imm8
    31105     0/imm32/no-disp32
    31106     0/imm32/no-xm32
    31107     0/imm32/no-x32
    31108     0x11/imm32/alloc-id:fake
    31109     _Primitive-xor-mem-with-reg/imm32/next
    31110 _Primitive-xor-mem-with-reg:  # (payload primitive)
    31111     0x11/imm32/alloc-id:fake:payload
    31112     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
    31113     0x11/imm32/alloc-id:fake
    31114     _string-xor/imm32/name
    31115     0x11/imm32/alloc-id:fake
    31116     Single-int-var-in-mem/imm32/inouts
    31117     0x11/imm32/alloc-id:fake
    31118     Single-int-var-in-some-register/imm32/outputs
    31119     0x11/imm32/alloc-id:fake
    31120     _string_33_xor/imm32/subx-name
    31121     1/imm32/rm32-is-first-inout
    31122     3/imm32/r32-is-first-output
    31123     0/imm32/no-imm32
    31124     0/imm32/no-imm8
    31125     0/imm32/no-disp32
    31126     0/imm32/no-xm32
    31127     0/imm32/no-x32
    31128     0x11/imm32/alloc-id:fake
    31129     _Primitive-xor-lit-with-reg/imm32/next
    31130 _Primitive-xor-lit-with-reg:  # (payload primitive)
    31131     0x11/imm32/alloc-id:fake:payload
    31132     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
    31133     0x11/imm32/alloc-id:fake
    31134     _string-xor/imm32/name
    31135     0x11/imm32/alloc-id:fake
    31136     Single-lit-var/imm32/inouts
    31137     0x11/imm32/alloc-id:fake
    31138     Single-int-var-in-some-register/imm32/outputs
    31139     0x11/imm32/alloc-id:fake
    31140     _string_81_subop_xor/imm32/subx-name
    31141     3/imm32/rm32-is-first-output
    31142     0/imm32/no-r32
    31143     1/imm32/imm32-is-first-inout
    31144     0/imm32/no-imm8
    31145     0/imm32/no-disp32
    31146     0/imm32/no-xm32
    31147     0/imm32/no-x32
    31148     0x11/imm32/alloc-id:fake
    31149     _Primitive-xor-lit-with-mem/imm32/next
    31150 _Primitive-xor-lit-with-mem:  # (payload primitive)
    31151     0x11/imm32/alloc-id:fake:payload
    31152     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
    31153     0x11/imm32/alloc-id:fake
    31154     _string-xor-with/imm32/name
    31155     0x11/imm32/alloc-id:fake
    31156     Int-var-and-literal/imm32/inouts
    31157     0/imm32/no-outputs
    31158     0/imm32/no-outputs
    31159     0x11/imm32/alloc-id:fake
    31160     _string_81_subop_xor/imm32/subx-name
    31161     1/imm32/rm32-is-first-inout
    31162     0/imm32/no-r32
    31163     2/imm32/imm32-is-second-inout
    31164     0/imm32/no-imm8
    31165     0/imm32/no-disp32
    31166     0/imm32/no-xm32
    31167     0/imm32/no-x32
    31168     0x11/imm32/alloc-id:fake
    31169     _Primitive-shift-reg-left-by-lit/imm32/next
    31170 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
    31171     0x11/imm32/alloc-id:fake:payload
    31172     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31173     0x11/imm32/alloc-id:fake
    31174     _string-shift-left/imm32/name
    31175     0x11/imm32/alloc-id:fake
    31176     Single-lit-var/imm32/inouts
    31177     0x11/imm32/alloc-id:fake
    31178     Single-int-var-in-some-register/imm32/outputs
    31179     0x11/imm32/alloc-id:fake
    31180     _string_c1_subop_shift_left/imm32/subx-name
    31181     3/imm32/rm32-is-first-output
    31182     0/imm32/no-r32
    31183     0/imm32/no-imm32
    31184     1/imm32/imm8-is-first-inout
    31185     0/imm32/no-disp32
    31186     0/imm32/no-xm32
    31187     0/imm32/no-x32
    31188     0x11/imm32/alloc-id:fake
    31189     _Primitive-shift-reg-right-by-lit/imm32/next
    31190 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
    31191     0x11/imm32/alloc-id:fake:payload
    31192     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31193     0x11/imm32/alloc-id:fake
    31194     _string-shift-right/imm32/name
    31195     0x11/imm32/alloc-id:fake
    31196     Single-lit-var/imm32/inouts
    31197     0x11/imm32/alloc-id:fake
    31198     Single-int-var-in-some-register/imm32/outputs
    31199     0x11/imm32/alloc-id:fake
    31200     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31201     3/imm32/rm32-is-first-output
    31202     0/imm32/no-r32
    31203     0/imm32/no-imm32
    31204     1/imm32/imm8-is-first-inout
    31205     0/imm32/no-disp32
    31206     0/imm32/no-xm32
    31207     0/imm32/no-x32
    31208     0x11/imm32/alloc-id:fake
    31209     _Primitive-shift-reg-right-signed-by-lit/imm32/next
    31210 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
    31211     0x11/imm32/alloc-id:fake:payload
    31212     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31213     0x11/imm32/alloc-id:fake
    31214     _string-shift-right-signed/imm32/name
    31215     0x11/imm32/alloc-id:fake
    31216     Single-lit-var/imm32/inouts
    31217     0x11/imm32/alloc-id:fake
    31218     Single-int-var-in-some-register/imm32/outputs
    31219     0x11/imm32/alloc-id:fake
    31220     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31221     3/imm32/rm32-is-first-output
    31222     0/imm32/no-r32
    31223     0/imm32/no-imm32
    31224     1/imm32/imm8-is-first-inout
    31225     0/imm32/no-disp32
    31226     0/imm32/no-xm32
    31227     0/imm32/no-x32
    31228     0x11/imm32/alloc-id:fake
    31229     _Primitive-shift-mem-left-by-lit/imm32/next
    31230 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
    31231     0x11/imm32/alloc-id:fake:payload
    31232     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31233     0x11/imm32/alloc-id:fake
    31234     _string-shift-left/imm32/name
    31235     0x11/imm32/alloc-id:fake
    31236     Int-var-and-literal/imm32/inouts
    31237     0/imm32/no-outputs
    31238     0/imm32/no-outputs
    31239     0x11/imm32/alloc-id:fake
    31240     _string_c1_subop_shift_left/imm32/subx-name
    31241     1/imm32/rm32-is-first-inout
    31242     0/imm32/no-r32
    31243     0/imm32/no-imm32
    31244     2/imm32/imm8-is-second-inout
    31245     0/imm32/no-disp32
    31246     0/imm32/no-xm32
    31247     0/imm32/no-x32
    31248     0x11/imm32/alloc-id:fake
    31249     _Primitive-shift-mem-right-by-lit/imm32/next
    31250 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
    31251     0x11/imm32/alloc-id:fake:payload
    31252     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31253     0x11/imm32/alloc-id:fake
    31254     _string-shift-right/imm32/name
    31255     0x11/imm32/alloc-id:fake
    31256     Int-var-and-literal/imm32/inouts
    31257     0/imm32/no-outputs
    31258     0/imm32/no-outputs
    31259     0x11/imm32/alloc-id:fake
    31260     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31261     1/imm32/rm32-is-first-inout
    31262     0/imm32/no-r32
    31263     0/imm32/no-imm32
    31264     2/imm32/imm8-is-second-inout
    31265     0/imm32/no-disp32
    31266     0/imm32/no-xm32
    31267     0/imm32/no-x32
    31268     0x11/imm32/alloc-id:fake
    31269     _Primitive-shift-mem-right-signed-by-lit/imm32/next
    31270 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
    31271     0x11/imm32/alloc-id:fake:payload
    31272     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31273     0x11/imm32/alloc-id:fake
    31274     _string-shift-right-signed/imm32/name
    31275     0x11/imm32/alloc-id:fake
    31276     Int-var-and-literal/imm32/inouts
    31277     0/imm32/no-outputs
    31278     0/imm32/no-outputs
    31279     0x11/imm32/alloc-id:fake
    31280     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31281     1/imm32/rm32-is-first-inout
    31282     0/imm32/no-r32
    31283     0/imm32/no-imm32
    31284     2/imm32/imm8-is-second-inout
    31285     0/imm32/no-disp32
    31286     0/imm32/no-xm32
    31287     0/imm32/no-x32
    31288     0x11/imm32/alloc-id:fake
    31289     _Primitive-copy-to-eax/imm32/next
    31290 # - copy
    31291 _Primitive-copy-to-eax:  # (payload primitive)
    31292     0x11/imm32/alloc-id:fake:payload
    31293     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
    31294     0x11/imm32/alloc-id:fake
    31295     _string-copy/imm32/name
    31296     0x11/imm32/alloc-id:fake
    31297     Single-lit-var/imm32/inouts
    31298     0x11/imm32/alloc-id:fake
    31299     Single-int-var-in-eax/imm32/outputs
    31300     0x11/imm32/alloc-id:fake
    31301     _string_b8_copy_to_eax/imm32/subx-name
    31302     0/imm32/no-rm32
    31303     0/imm32/no-r32
    31304     1/imm32/imm32-is-first-inout
    31305     0/imm32/no-imm8
    31306     0/imm32/no-disp32
    31307     0/imm32/no-xm32
    31308     0/imm32/no-x32
    31309     0x11/imm32/alloc-id:fake
    31310     _Primitive-copy-to-ecx/imm32/next
    31311 _Primitive-copy-to-ecx:  # (payload primitive)
    31312     0x11/imm32/alloc-id:fake:payload
    31313     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
    31314     0x11/imm32/alloc-id:fake
    31315     _string-copy/imm32/name
    31316     0x11/imm32/alloc-id:fake
    31317     Single-lit-var/imm32/inouts
    31318     0x11/imm32/alloc-id:fake
    31319     Single-int-var-in-ecx/imm32/outputs
    31320     0x11/imm32/alloc-id:fake
    31321     _string_b9_copy_to_ecx/imm32/subx-name
    31322     0/imm32/no-rm32
    31323     0/imm32/no-r32
    31324     1/imm32/imm32-is-first-inout
    31325     0/imm32/no-imm8
    31326     0/imm32/no-disp32
    31327     0/imm32/no-xm32
    31328     0/imm32/no-x32
    31329     0x11/imm32/alloc-id:fake
    31330     _Primitive-copy-to-edx/imm32/next
    31331 _Primitive-copy-to-edx:  # (payload primitive)
    31332     0x11/imm32/alloc-id:fake:payload
    31333     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
    31334     0x11/imm32/alloc-id:fake
    31335     _string-copy/imm32/name
    31336     0x11/imm32/alloc-id:fake
    31337     Single-lit-var/imm32/inouts
    31338     0x11/imm32/alloc-id:fake
    31339     Single-int-var-in-edx/imm32/outputs
    31340     0x11/imm32/alloc-id:fake
    31341     _string_ba_copy_to_edx/imm32/subx-name
    31342     0/imm32/no-rm32
    31343     0/imm32/no-r32
    31344     1/imm32/imm32-is-first-inout
    31345     0/imm32/no-imm8
    31346     0/imm32/no-disp32
    31347     0/imm32/no-xm32
    31348     0/imm32/no-x32
    31349     0x11/imm32/alloc-id:fake
    31350     _Primitive-copy-to-ebx/imm32/next
    31351 _Primitive-copy-to-ebx:  # (payload primitive)
    31352     0x11/imm32/alloc-id:fake:payload
    31353     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
    31354     0x11/imm32/alloc-id:fake
    31355     _string-copy/imm32/name
    31356     0x11/imm32/alloc-id:fake
    31357     Single-lit-var/imm32/inouts
    31358     0x11/imm32/alloc-id:fake
    31359     Single-int-var-in-ebx/imm32/outputs
    31360     0x11/imm32/alloc-id:fake
    31361     _string_bb_copy_to_ebx/imm32/subx-name
    31362     0/imm32/no-rm32
    31363     0/imm32/no-r32
    31364     1/imm32/imm32-is-first-inout
    31365     0/imm32/no-imm8
    31366     0/imm32/no-disp32
    31367     0/imm32/no-xm32
    31368     0/imm32/no-x32
    31369     0x11/imm32/alloc-id:fake
    31370     _Primitive-copy-to-esi/imm32/next
    31371 _Primitive-copy-to-esi:  # (payload primitive)
    31372     0x11/imm32/alloc-id:fake:payload
    31373     # var/esi <- copy lit => be/copy-to-esi lit/imm32
    31374     0x11/imm32/alloc-id:fake
    31375     _string-copy/imm32/name
    31376     0x11/imm32/alloc-id:fake
    31377     Single-lit-var/imm32/inouts
    31378     0x11/imm32/alloc-id:fake
    31379     Single-int-var-in-esi/imm32/outputs
    31380     0x11/imm32/alloc-id:fake
    31381     _string_be_copy_to_esi/imm32/subx-name
    31382     0/imm32/no-rm32
    31383     0/imm32/no-r32
    31384     1/imm32/imm32-is-first-inout
    31385     0/imm32/no-imm8
    31386     0/imm32/no-disp32
    31387     0/imm32/no-xm32
    31388     0/imm32/no-x32
    31389     0x11/imm32/alloc-id:fake
    31390     _Primitive-copy-to-edi/imm32/next
    31391 _Primitive-copy-to-edi:  # (payload primitive)
    31392     0x11/imm32/alloc-id:fake:payload
    31393     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
    31394     0x11/imm32/alloc-id:fake
    31395     _string-copy/imm32/name
    31396     0x11/imm32/alloc-id:fake
    31397     Single-lit-var/imm32/inouts
    31398     0x11/imm32/alloc-id:fake
    31399     Single-int-var-in-edi/imm32/outputs
    31400     0x11/imm32/alloc-id:fake
    31401     _string_bf_copy_to_edi/imm32/subx-name
    31402     0/imm32/no-rm32
    31403     0/imm32/no-r32
    31404     1/imm32/imm32-is-first-inout
    31405     0/imm32/no-imm8
    31406     0/imm32/no-disp32
    31407     0/imm32/no-xm32
    31408     0/imm32/no-x32
    31409     0x11/imm32/alloc-id:fake
    31410     _Primitive-copy-reg-to-reg/imm32/next
    31411 _Primitive-copy-reg-to-reg:  # (payload primitive)
    31412     0x11/imm32/alloc-id:fake:payload
    31413     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
    31414     0x11/imm32/alloc-id:fake
    31415     _string-copy/imm32/name
    31416     0x11/imm32/alloc-id:fake
    31417     Single-int-var-in-some-register/imm32/inouts
    31418     0x11/imm32/alloc-id:fake
    31419     Single-int-var-in-some-register/imm32/outputs
    31420     0x11/imm32/alloc-id:fake
    31421     _string_89_<-/imm32/subx-name
    31422     3/imm32/rm32-is-first-output
    31423     1/imm32/r32-is-first-inout
    31424     0/imm32/no-imm32
    31425     0/imm32/no-imm8
    31426     0/imm32/no-disp32
    31427     0/imm32/no-xm32
    31428     0/imm32/no-x32
    31429     0x11/imm32/alloc-id:fake
    31430     _Primitive-copy-reg-to-mem/imm32/next
    31431 _Primitive-copy-reg-to-mem:  # (payload primitive)
    31432     0x11/imm32/alloc-id:fake:payload
    31433     # copy-to var1 var2/reg => 89/<- var1 var2/r32
    31434     0x11/imm32/alloc-id:fake
    31435     _string-copy-to/imm32/name
    31436     0x11/imm32/alloc-id:fake
    31437     Two-args-int-stack-int-reg/imm32/inouts
    31438     0/imm32/no-outputs
    31439     0/imm32/no-outputs
    31440     0x11/imm32/alloc-id:fake
    31441     _string_89_<-/imm32/subx-name
    31442     1/imm32/rm32-is-first-inout
    31443     2/imm32/r32-is-second-inout
    31444     0/imm32/no-imm32
    31445     0/imm32/no-imm8
    31446     0/imm32/no-disp32
    31447     0/imm32/no-xm32
    31448     0/imm32/no-x32
    31449     0x11/imm32/alloc-id:fake
    31450     _Primitive-copy-mem-to-reg/imm32/next
    31451 _Primitive-copy-mem-to-reg:  # (payload primitive)
    31452     0x11/imm32/alloc-id:fake:payload
    31453     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
    31454     0x11/imm32/alloc-id:fake
    31455     _string-copy/imm32/name
    31456     0x11/imm32/alloc-id:fake
    31457     Single-int-var-in-mem/imm32/inouts
    31458     0x11/imm32/alloc-id:fake
    31459     Single-int-var-in-some-register/imm32/outputs
    31460     0x11/imm32/alloc-id:fake
    31461     _string_8b_->/imm32/subx-name
    31462     1/imm32/rm32-is-first-inout
    31463     3/imm32/r32-is-first-output
    31464     0/imm32/no-imm32
    31465     0/imm32/no-imm8
    31466     0/imm32/no-disp32
    31467     0/imm32/no-xm32
    31468     0/imm32/no-x32
    31469     0x11/imm32/alloc-id:fake
    31470     _Primitive-copy-lit-to-reg/imm32/next
    31471 _Primitive-copy-lit-to-reg:  # (payload primitive)
    31472     0x11/imm32/alloc-id:fake:payload
    31473     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
    31474     0x11/imm32/alloc-id:fake
    31475     _string-copy/imm32/name
    31476     0x11/imm32/alloc-id:fake
    31477     Single-lit-var/imm32/inouts
    31478     0x11/imm32/alloc-id:fake
    31479     Single-int-var-in-some-register/imm32/outputs
    31480     0x11/imm32/alloc-id:fake
    31481     _string_c7_subop_copy/imm32/subx-name
    31482     3/imm32/rm32-is-first-output
    31483     0/imm32/no-r32
    31484     1/imm32/imm32-is-first-inout
    31485     0/imm32/no-imm8
    31486     0/imm32/no-disp32
    31487     0/imm32/no-xm32
    31488     0/imm32/no-x32
    31489     0x11/imm32/alloc-id:fake
    31490     _Primitive-copy-lit-to-mem/imm32/next
    31491 _Primitive-copy-lit-to-mem:  # (payload primitive)
    31492     0x11/imm32/alloc-id:fake:payload
    31493     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
    31494     0x11/imm32/alloc-id:fake
    31495     _string-copy-to/imm32/name
    31496     0x11/imm32/alloc-id:fake
    31497     Int-var-and-literal/imm32/inouts
    31498     0/imm32/no-outputs
    31499     0/imm32/no-outputs
    31500     0x11/imm32/alloc-id:fake
    31501     _string_c7_subop_copy/imm32/subx-name
    31502     1/imm32/rm32-is-first-inout
    31503     0/imm32/no-r32
    31504     2/imm32/imm32-is-second-inout
    31505     0/imm32/no-imm8
    31506     0/imm32/no-disp32
    31507     0/imm32/no-xm32
    31508     0/imm32/no-x32
    31509     0x11/imm32/alloc-id:fake
    31510     _Primitive-copy-byte-from-reg/imm32/next
    31511 # - copy byte
    31512 _Primitive-copy-byte-from-reg:
    31513     0x11/imm32/alloc-id:fake:payload
    31514     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
    31515     0x11/imm32/alloc-id:fake
    31516     _string-copy-byte/imm32/name
    31517     0x11/imm32/alloc-id:fake
    31518     Single-byte-var-in-some-register/imm32/inouts
    31519     0x11/imm32/alloc-id:fake
    31520     Single-byte-var-in-some-register/imm32/outputs
    31521     0x11/imm32/alloc-id:fake
    31522     _string_8a_copy_byte/imm32/subx-name
    31523     1/imm32/rm32-is-first-inout
    31524     3/imm32/r32-is-first-output
    31525     0/imm32/no-imm32
    31526     0/imm32/no-imm8
    31527     0/imm32/no-disp32
    31528     0/imm32/no-xm32
    31529     0/imm32/no-x32
    31530     0x11/imm32/alloc-id:fake
    31531     _Primitive-copy-byte-from-mem/imm32/next
    31532 _Primitive-copy-byte-from-mem:
    31533     0x11/imm32/alloc-id:fake:payload
    31534     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
    31535     0x11/imm32/alloc-id:fake
    31536     _string-copy-byte/imm32/name
    31537     0x11/imm32/alloc-id:fake
    31538     Single-byte-var-in-mem/imm32/inouts
    31539     0x11/imm32/alloc-id:fake
    31540     Single-byte-var-in-some-register/imm32/outputs
    31541     0x11/imm32/alloc-id:fake
    31542     _string_8a_copy_byte/imm32/subx-name
    31543     1/imm32/rm32-is-first-inout
    31544     3/imm32/r32-is-first-output
    31545     0/imm32/no-imm32
    31546     0/imm32/no-imm8
    31547     0/imm32/no-disp32
    31548     0/imm32/no-xm32
    31549     0/imm32/no-x32
    31550     0x11/imm32/alloc-id:fake
    31551     _Primitive-copy-byte-to-mem/imm32/next
    31552 _Primitive-copy-byte-to-mem:
    31553     0x11/imm32/alloc-id:fake:payload
    31554     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
    31555     0x11/imm32/alloc-id:fake
    31556     _string-copy-byte-to/imm32/name
    31557     0x11/imm32/alloc-id:fake
    31558     Two-args-byte-stack-byte-reg/imm32/inouts
    31559     0/imm32/no-outputs
    31560     0/imm32/no-outputs
    31561     0x11/imm32/alloc-id:fake
    31562     _string_88_copy_byte/imm32/subx-name
    31563     1/imm32/rm32-is-first-inout
    31564     2/imm32/r32-is-second-inout
    31565     0/imm32/no-imm32
    31566     0/imm32/no-imm8
    31567     0/imm32/no-disp32
    31568     0/imm32/no-xm32
    31569     0/imm32/no-x32
    31570     0x11/imm32/alloc-id:fake
    31571     _Primitive-address/imm32/next
    31572 # - address
    31573 _Primitive-address:  # (payload primitive)
    31574     0x11/imm32/alloc-id:fake:payload
    31575     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    31576     0x11/imm32/alloc-id:fake
    31577     _string-address/imm32/name
    31578     0x11/imm32/alloc-id:fake
    31579     Single-int-var-in-mem/imm32/inouts
    31580     0x11/imm32/alloc-id:fake
    31581     Single-addr-var-in-some-register/imm32/outputs
    31582     0x11/imm32/alloc-id:fake
    31583     _string_8d_copy_address/imm32/subx-name
    31584     1/imm32/rm32-is-first-inout
    31585     3/imm32/r32-is-first-output
    31586     0/imm32/no-imm32
    31587     0/imm32/no-imm8
    31588     0/imm32/no-disp32
    31589     0/imm32/no-xm32
    31590     0/imm32/no-x32
    31591     0x11/imm32/alloc-id:fake
    31592     _Primitive-compare-reg-with-reg/imm32/next
    31593 # - compare
    31594 _Primitive-compare-reg-with-reg:  # (payload primitive)
    31595     0x11/imm32/alloc-id:fake:payload
    31596     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
    31597     0x11/imm32/alloc-id:fake
    31598     _string-compare/imm32/name
    31599     0x11/imm32/alloc-id:fake
    31600     Two-int-args-in-regs/imm32/inouts
    31601     0/imm32/no-outputs
    31602     0/imm32/no-outputs
    31603     0x11/imm32/alloc-id:fake
    31604     _string_39_compare->/imm32/subx-name
    31605     1/imm32/rm32-is-first-inout
    31606     2/imm32/r32-is-second-inout
    31607     0/imm32/no-imm32
    31608     0/imm32/no-imm8
    31609     0/imm32/no-disp32
    31610     0/imm32/no-xm32
    31611     0/imm32/no-x32
    31612     0x11/imm32/alloc-id:fake
    31613     _Primitive-compare-mem-with-reg/imm32/next
    31614 _Primitive-compare-mem-with-reg:  # (payload primitive)
    31615     0x11/imm32/alloc-id:fake:payload
    31616     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
    31617     0x11/imm32/alloc-id:fake
    31618     _string-compare/imm32/name
    31619     0x11/imm32/alloc-id:fake
    31620     Two-args-int-stack-int-reg/imm32/inouts
    31621     0/imm32/no-outputs
    31622     0/imm32/no-outputs
    31623     0x11/imm32/alloc-id:fake
    31624     _string_39_compare->/imm32/subx-name
    31625     1/imm32/rm32-is-first-inout
    31626     2/imm32/r32-is-second-inout
    31627     0/imm32/no-imm32
    31628     0/imm32/no-imm8
    31629     0/imm32/no-disp32
    31630     0/imm32/no-xm32
    31631     0/imm32/no-x32
    31632     0x11/imm32/alloc-id:fake
    31633     _Primitive-compare-reg-with-mem/imm32/next
    31634 _Primitive-compare-reg-with-mem:  # (payload primitive)
    31635     0x11/imm32/alloc-id:fake:payload
    31636     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
    31637     0x11/imm32/alloc-id:fake
    31638     _string-compare/imm32/name
    31639     0x11/imm32/alloc-id:fake
    31640     Two-args-int-reg-int-stack/imm32/inouts
    31641     0/imm32/no-outputs
    31642     0/imm32/no-outputs
    31643     0x11/imm32/alloc-id:fake
    31644     _string_3b_compare<-/imm32/subx-name
    31645     2/imm32/rm32-is-second-inout
    31646     1/imm32/r32-is-first-inout
    31647     0/imm32/no-imm32
    31648     0/imm32/no-imm8
    31649     0/imm32/no-disp32
    31650     0/imm32/no-xm32
    31651     0/imm32/no-x32
    31652     0x11/imm32/alloc-id:fake
    31653     _Primitive-compare-eax-with-literal/imm32/next
    31654 _Primitive-compare-eax-with-literal:  # (payload primitive)
    31655     0x11/imm32/alloc-id:fake:payload
    31656     # compare var1/eax n => 3d/compare-eax-with n/imm32
    31657     0x11/imm32/alloc-id:fake
    31658     _string-compare/imm32/name
    31659     0x11/imm32/alloc-id:fake
    31660     Two-args-int-eax-int-literal/imm32/inouts
    31661     0/imm32/no-outputs
    31662     0/imm32/no-outputs
    31663     0x11/imm32/alloc-id:fake
    31664     _string_3d_compare_eax_with/imm32/subx-name
    31665     0/imm32/no-rm32
    31666     0/imm32/no-r32
    31667     2/imm32/imm32-is-second-inout
    31668     0/imm32/no-imm8
    31669     0/imm32/no-disp32
    31670     0/imm32/no-xm32
    31671     0/imm32/no-x32
    31672     0x11/imm32/alloc-id:fake
    31673     _Primitive-compare-reg-with-literal/imm32/next
    31674 _Primitive-compare-reg-with-literal:  # (payload primitive)
    31675     0x11/imm32/alloc-id:fake:payload
    31676     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
    31677     0x11/imm32/alloc-id:fake
    31678     _string-compare/imm32/name
    31679     0x11/imm32/alloc-id:fake
    31680     Int-var-in-register-and-literal/imm32/inouts
    31681     0/imm32/no-outputs
    31682     0/imm32/no-outputs
    31683     0x11/imm32/alloc-id:fake
    31684     _string_81_subop_compare/imm32/subx-name
    31685     1/imm32/rm32-is-first-inout
    31686     0/imm32/no-r32
    31687     2/imm32/imm32-is-second-inout
    31688     0/imm32/no-imm8
    31689     0/imm32/no-disp32
    31690     0/imm32/no-xm32
    31691     0/imm32/no-x32
    31692     0x11/imm32/alloc-id:fake
    31693     _Primitive-compare-mem-with-literal/imm32/next
    31694 _Primitive-compare-mem-with-literal:  # (payload primitive)
    31695     0x11/imm32/alloc-id:fake:payload
    31696     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
    31697     0x11/imm32/alloc-id:fake
    31698     _string-compare/imm32/name
    31699     0x11/imm32/alloc-id:fake
    31700     Int-var-and-literal/imm32/inouts
    31701     0/imm32/no-outputs
    31702     0/imm32/no-outputs
    31703     0x11/imm32/alloc-id:fake
    31704     _string_81_subop_compare/imm32/subx-name
    31705     1/imm32/rm32-is-first-inout
    31706     0/imm32/no-r32
    31707     2/imm32/imm32-is-second-inout
    31708     0/imm32/no-imm8
    31709     0/imm32/no-disp32
    31710     0/imm32/no-xm32
    31711     0/imm32/no-x32
    31712     0x11/imm32/alloc-id:fake
    31713     _Primitive-negate-reg/imm32/next
    31714 # - negate
    31715 _Primitive-negate-reg:  # (payload primitive)
    31716     0x11/imm32/alloc-id:fake:payload
    31717     # var1/reg <- negate => f7 3/subop/negate var1/rm32
    31718     0x11/imm32/alloc-id:fake
    31719     _string-negate/imm32/name
    31720     0/imm32/no-inouts
    31721     0/imm32/no-inouts
    31722     0x11/imm32/alloc-id:fake
    31723     Single-int-var-in-some-register/imm32/outputs
    31724     0x11/imm32/alloc-id:fake
    31725     _string_f7_subop_negate/imm32/subx-name
    31726     3/imm32/rm32-is-first-output
    31727     0/imm32/no-r32
    31728     0/imm32/no-imm32
    31729     0/imm32/no-imm8
    31730     0/imm32/no-disp32
    31731     0/imm32/no-xm32
    31732     0/imm32/no-x32
    31733     0x11/imm32/alloc-id:fake
    31734     _Primitive-negate-mem/imm32/next
    31735 _Primitive-negate-mem:  # (payload primitive)
    31736     0x11/imm32/alloc-id:fake:payload
    31737     # negate var1 => f7 3/subop/negate var1/rm32
    31738     0x11/imm32/alloc-id:fake
    31739     _string-negate/imm32/name
    31740     0x11/imm32/alloc-id:fake
    31741     Single-int-var-in-mem/imm32/inouts
    31742     0/imm32/no-outputs
    31743     0/imm32/no-outputs
    31744     0x11/imm32/alloc-id:fake
    31745     _string_f7_subop_negate/imm32/subx-name
    31746     1/imm32/rm32-is-first-inout
    31747     0/imm32/no-r32
    31748     0/imm32/no-imm32
    31749     0/imm32/no-imm8
    31750     0/imm32/no-disp32
    31751     0/imm32/no-xm32
    31752     0/imm32/no-x32
    31753     0x11/imm32/alloc-id:fake
    31754     _Primitive-multiply-reg-by-reg/imm32/next
    31755 # - multiply
    31756 _Primitive-multiply-reg-by-reg:  # (payload primitive)
    31757     0x11/imm32/alloc-id:fake:payload
    31758     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    31759     0x11/imm32/alloc-id:fake
    31760     _string-multiply/imm32/name
    31761     0x11/imm32/alloc-id:fake
    31762     Single-int-var-in-some-register/imm32/inouts
    31763     0x11/imm32/alloc-id:fake
    31764     Single-int-var-in-some-register/imm32/outputs
    31765     0x11/imm32/alloc-id:fake
    31766     _string_0f_af_multiply/imm32/subx-name
    31767     1/imm32/rm32-is-first-inout
    31768     3/imm32/r32-is-first-output
    31769     0/imm32/no-imm32
    31770     0/imm32/no-imm8
    31771     0/imm32/no-disp32
    31772     0/imm32/no-xm32
    31773     0/imm32/no-x32
    31774     0x11/imm32/alloc-id:fake
    31775     _Primitive-multiply-reg-by-mem/imm32/next
    31776 _Primitive-multiply-reg-by-mem:  # (payload primitive)
    31777     0x11/imm32/alloc-id:fake:payload
    31778     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    31779     0x11/imm32/alloc-id:fake
    31780     _string-multiply/imm32/name
    31781     0x11/imm32/alloc-id:fake
    31782     Single-int-var-in-mem/imm32/inouts
    31783     0x11/imm32/alloc-id:fake
    31784     Single-int-var-in-some-register/imm32/outputs
    31785     0x11/imm32/alloc-id:fake
    31786     _string_0f_af_multiply/imm32/subx-name
    31787     1/imm32/rm32-is-first-inout
    31788     3/imm32/r32-is-first-output
    31789     0/imm32/no-imm32
    31790     0/imm32/no-imm8
    31791     0/imm32/no-disp32
    31792     0/imm32/no-xm32
    31793     0/imm32/no-x32
    31794     0x11/imm32/alloc-id:fake
    31795     _Primitive-convert-mem-to-xreg/imm32/next
    31796 # - convert int to floating point
    31797 _Primitive-convert-mem-to-xreg:  # (payload primitive)
    31798     0x11/imm32/alloc-id:fake:payload
    31799     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    31800     0x11/imm32/alloc-id:fake
    31801     _string-convert/imm32/name
    31802     0x11/imm32/alloc-id:fake
    31803     Single-int-var-in-mem/imm32/inouts
    31804     0x11/imm32/alloc-id:fake
    31805     Single-float-var-in-some-register/imm32/outputs
    31806     0x11/imm32/alloc-id:fake
    31807     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    31808     1/imm32/rm32-is-first-inout
    31809     0/imm32/no-r32
    31810     0/imm32/no-imm32
    31811     0/imm32/no-imm8
    31812     0/imm32/no-disp32
    31813     0/imm32/no-xm32
    31814     3/imm32/x32-is-first-output
    31815     0x11/imm32/alloc-id:fake
    31816     _Primitive-convert-reg-to-xreg/imm32/next
    31817 _Primitive-convert-reg-to-xreg:  # (payload primitive)
    31818     0x11/imm32/alloc-id:fake:payload
    31819     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    31820     0x11/imm32/alloc-id:fake
    31821     _string-convert/imm32/name
    31822     0x11/imm32/alloc-id:fake
    31823     Single-int-var-in-some-register/imm32/inouts
    31824     0x11/imm32/alloc-id:fake
    31825     Single-float-var-in-some-register/imm32/outputs
    31826     0x11/imm32/alloc-id:fake
    31827     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    31828     1/imm32/rm32-is-first-inout
    31829     0/imm32/no-r32
    31830     0/imm32/no-imm32
    31831     0/imm32/no-imm8
    31832     0/imm32/no-disp32
    31833     0/imm32/no-xm32
    31834     3/imm32/x32-is-first-output
    31835     0x11/imm32/alloc-id:fake
    31836     _Primitive-convert-xmem-to-reg/imm32/next
    31837 # - convert floating point to int
    31838 _Primitive-convert-xmem-to-reg:  # (payload primitive)
    31839     0x11/imm32/alloc-id:fake:payload
    31840     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    31841     0x11/imm32/alloc-id:fake
    31842     _string-convert/imm32/name
    31843     0x11/imm32/alloc-id:fake
    31844     Single-float-var-in-mem/imm32/inouts
    31845     0x11/imm32/alloc-id:fake
    31846     Single-int-var-in-some-register/imm32/outputs
    31847     0x11/imm32/alloc-id:fake
    31848     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    31849     0/imm32/no-rm32
    31850     3/imm32/r32-is-first-output
    31851     0/imm32/no-imm32
    31852     0/imm32/no-imm8
    31853     0/imm32/no-disp32
    31854     1/imm32/xm32-is-first-inout
    31855     0/imm32/no-x32
    31856     0x11/imm32/alloc-id:fake
    31857     _Primitive-convert-xreg-to-reg/imm32/next
    31858 _Primitive-convert-xreg-to-reg:  # (payload primitive)
    31859     0x11/imm32/alloc-id:fake:payload
    31860     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    31861     0x11/imm32/alloc-id:fake
    31862     _string-convert/imm32/name
    31863     0x11/imm32/alloc-id:fake
    31864     Single-float-var-in-some-register/imm32/inouts
    31865     0x11/imm32/alloc-id:fake
    31866     Single-int-var-in-some-register/imm32/outputs
    31867     0x11/imm32/alloc-id:fake
    31868     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    31869     0/imm32/no-rm32
    31870     3/imm32/r32-is-first-output
    31871     0/imm32/no-imm32
    31872     0/imm32/no-imm8
    31873     0/imm32/no-disp32
    31874     1/imm32/xm32-is-first-inout
    31875     0/imm32/no-x32
    31876     0x11/imm32/alloc-id:fake
    31877     _Primitive-truncate-xmem-to-reg/imm32/next
    31878 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
    31879     0x11/imm32/alloc-id:fake:payload
    31880     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    31881     0x11/imm32/alloc-id:fake
    31882     _string-truncate/imm32/name
    31883     0x11/imm32/alloc-id:fake
    31884     Single-float-var-in-mem/imm32/inouts
    31885     0x11/imm32/alloc-id:fake
    31886     Single-int-var-in-some-register/imm32/outputs
    31887     0x11/imm32/alloc-id:fake
    31888     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    31889     0/imm32/no-rm32
    31890     3/imm32/r32-is-first-output
    31891     0/imm32/no-imm32
    31892     0/imm32/no-imm8
    31893     0/imm32/no-disp32
    31894     1/imm32/xm32-is-first-inout
    31895     0/imm32/no-x32
    31896     0x11/imm32/alloc-id:fake
    31897     _Primitive-truncate-xreg-to-reg/imm32/next
    31898 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
    31899     0x11/imm32/alloc-id:fake:payload
    31900     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    31901     0x11/imm32/alloc-id:fake
    31902     _string-truncate/imm32/name
    31903     0x11/imm32/alloc-id:fake
    31904     Single-float-var-in-some-register/imm32/inouts
    31905     0x11/imm32/alloc-id:fake
    31906     Single-int-var-in-some-register/imm32/outputs
    31907     0x11/imm32/alloc-id:fake
    31908     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    31909     0/imm32/no-rm32
    31910     3/imm32/r32-is-first-output
    31911     0/imm32/no-imm32
    31912     0/imm32/no-imm8
    31913     0/imm32/no-disp32
    31914     1/imm32/xm32-is-first-inout
    31915     0/imm32/no-x32
    31916     0x11/imm32/alloc-id:fake
    31917     _Primitive-reinterpret-xmem-as-reg/imm32/next
    31918 # - reinterpret bytes (just for debugging)
    31919 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
    31920     0x11/imm32/alloc-id:fake:payload
    31921     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
    31922     0x11/imm32/alloc-id:fake
    31923     _string-reinterpret/imm32/name
    31924     0x11/imm32/alloc-id:fake
    31925     Single-float-var-in-mem/imm32/inouts
    31926     0x11/imm32/alloc-id:fake
    31927     Single-int-var-in-some-register/imm32/outputs
    31928     0x11/imm32/alloc-id:fake
    31929     _string_8b_->/imm32/subx-name
    31930     0/imm32/no-rm32
    31931     3/imm32/r32-is-first-output
    31932     0/imm32/no-imm32
    31933     0/imm32/no-imm8
    31934     0/imm32/no-disp32
    31935     1/imm32/xm32-is-first-inout
    31936     0/imm32/no-x32
    31937     0x11/imm32/alloc-id:fake
    31938     _Primitive-reinterpret-mem-as-xreg/imm32/next
    31939 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
    31940     0x11/imm32/alloc-id:fake:payload
    31941     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
    31942     0x11/imm32/alloc-id:fake
    31943     _string-reinterpret/imm32/name
    31944     0x11/imm32/alloc-id:fake
    31945     Single-int-var-in-mem/imm32/inouts
    31946     0x11/imm32/alloc-id:fake
    31947     Single-float-var-in-some-register/imm32/outputs
    31948     0x11/imm32/alloc-id:fake
    31949     _string_f3_0f_10_copy/imm32/subx-name
    31950     1/imm32/rm32-is-first-inout
    31951     0/imm32/no-r32
    31952     0/imm32/no-imm32
    31953     0/imm32/no-imm8
    31954     0/imm32/no-disp32
    31955     0/imm32/no-xm32
    31956     3/imm32/x32-is-first-output
    31957     0x11/imm32/alloc-id:fake
    31958     _Primitive-copy-xreg-to-xreg/imm32/next
    31959 # - floating-point copy
    31960 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
    31961     0x11/imm32/alloc-id:fake:payload
    31962     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
    31963     0x11/imm32/alloc-id:fake
    31964     _string-copy/imm32/name
    31965     0x11/imm32/alloc-id:fake
    31966     Single-float-var-in-some-register/imm32/inouts
    31967     0x11/imm32/alloc-id:fake
    31968     Single-float-var-in-some-register/imm32/outputs
    31969     0x11/imm32/alloc-id:fake
    31970     _string_f3_0f_11_copy/imm32/subx-name
    31971     0/imm32/no-rm32
    31972     0/imm32/no-r32
    31973     0/imm32/no-imm32
    31974     0/imm32/no-imm8
    31975     0/imm32/no-disp32
    31976     3/imm32/xm32-is-first-output
    31977     1/imm32/x32-is-first-inout
    31978     0x11/imm32/alloc-id:fake
    31979     _Primitive-copy-xreg-to-mem/imm32/next
    31980 _Primitive-copy-xreg-to-mem:  # (payload primitive)
    31981     0x11/imm32/alloc-id:fake:payload
    31982     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
    31983     0x11/imm32/alloc-id:fake
    31984     _string-copy-to/imm32/name
    31985     0x11/imm32/alloc-id:fake
    31986     Two-args-float-stack-float-reg/imm32/inouts
    31987     0/imm32/no-outputs
    31988     0/imm32/no-outputs
    31989     0x11/imm32/alloc-id:fake
    31990     _string_f3_0f_11_copy/imm32/subx-name
    31991     0/imm32/no-rm32
    31992     0/imm32/no-r32
    31993     0/imm32/no-imm32
    31994     0/imm32/no-imm8
    31995     0/imm32/no-disp32
    31996     1/imm32/xm32-is-first-inout
    31997     2/imm32/x32-is-second-inout
    31998     0x11/imm32/alloc-id:fake
    31999     _Primitive-copy-mem-to-xreg/imm32/next
    32000 _Primitive-copy-mem-to-xreg:  # (payload primitive)
    32001     0x11/imm32/alloc-id:fake:payload
    32002     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
    32003     0x11/imm32/alloc-id:fake
    32004     _string-copy/imm32/name
    32005     0x11/imm32/alloc-id:fake
    32006     Single-float-var-in-mem/imm32/inouts
    32007     0x11/imm32/alloc-id:fake
    32008     Single-float-var-in-some-register/imm32/outputs
    32009     0x11/imm32/alloc-id:fake
    32010     _string_f3_0f_10_copy/imm32/subx-name
    32011     0/imm32/no-rm32
    32012     0/imm32/no-r32
    32013     0/imm32/no-imm32
    32014     0/imm32/no-imm8
    32015     0/imm32/no-disp32
    32016     1/imm32/xm32-is-first-inout
    32017     3/imm32/x32-is-first-output
    32018     0x11/imm32/alloc-id:fake
    32019     _Primitive-address-of-xmem/imm32/next
    32020 # - floating-point-address
    32021 _Primitive-address-of-xmem:  # (payload primitive)
    32022     0x11/imm32/alloc-id:fake:payload
    32023     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    32024     0x11/imm32/alloc-id:fake
    32025     _string-address/imm32/name
    32026     0x11/imm32/alloc-id:fake
    32027     Single-float-var-in-mem/imm32/inouts
    32028     0x11/imm32/alloc-id:fake
    32029     Single-addr-var-in-some-register/imm32/outputs
    32030     0x11/imm32/alloc-id:fake
    32031     _string_8d_copy_address/imm32/subx-name
    32032     1/imm32/rm32-is-first-inout
    32033     3/imm32/r32-is-first-output
    32034     0/imm32/no-imm32
    32035     0/imm32/no-imm8
    32036     0/imm32/no-disp32
    32037     0/imm32/no-xm32
    32038     0/imm32/no-x32
    32039     0x11/imm32/alloc-id:fake
    32040     _Primitive-add-xreg-to-xreg/imm32/next
    32041 # - floating-point add
    32042 _Primitive-add-xreg-to-xreg:  # (payload primitive)
    32043     0x11/imm32/alloc-id:fake:payload
    32044     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
    32045     0x11/imm32/alloc-id:fake
    32046     _string-add/imm32/name
    32047     0x11/imm32/alloc-id:fake
    32048     Single-float-var-in-some-register/imm32/inouts
    32049     0x11/imm32/alloc-id:fake
    32050     Single-float-var-in-some-register/imm32/outputs
    32051     0x11/imm32/alloc-id:fake
    32052     _string_f3_0f_58_add/imm32/subx-name
    32053     0/imm32/no-rm32
    32054     0/imm32/no-r32
    32055     0/imm32/no-imm32
    32056     0/imm32/no-imm8
    32057     0/imm32/no-disp32
    32058     1/imm32/xm32-is-first-inout
    32059     3/imm32/x32-is-first-output
    32060     0x11/imm32/alloc-id:fake
    32061     _Primitive-add-mem-to-xreg/imm32/next
    32062 _Primitive-add-mem-to-xreg:  # (payload primitive)
    32063     0x11/imm32/alloc-id:fake:payload
    32064     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
    32065     0x11/imm32/alloc-id:fake
    32066     _string-add/imm32/name
    32067     0x11/imm32/alloc-id:fake
    32068     Single-float-var-in-mem/imm32/inouts
    32069     0x11/imm32/alloc-id:fake
    32070     Single-float-var-in-some-register/imm32/outputs
    32071     0x11/imm32/alloc-id:fake
    32072     _string_f3_0f_58_add/imm32/subx-name
    32073     0/imm32/no-rm32
    32074     0/imm32/no-r32
    32075     0/imm32/no-imm32
    32076     0/imm32/no-imm8
    32077     0/imm32/no-disp32
    32078     1/imm32/xm32-is-first-inout
    32079     3/imm32/x32-is-first-output
    32080     0x11/imm32/alloc-id:fake
    32081     _Primitive-subtract-xreg-from-xreg/imm32/next
    32082 # - floating-point subtract
    32083 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
    32084     0x11/imm32/alloc-id:fake:payload
    32085     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
    32086     0x11/imm32/alloc-id:fake
    32087     _string-subtract/imm32/name
    32088     0x11/imm32/alloc-id:fake
    32089     Single-float-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_5c_subtract/imm32/subx-name
    32094     0/imm32/no-rm32
    32095     0/imm32/no-r32
    32096     0/imm32/no-imm32
    32097     0/imm32/no-imm8
    32098     0/imm32/no-disp32
    32099     1/imm32/xm32-is-first-inout
    32100     3/imm32/x32-is-first-output
    32101     0x11/imm32/alloc-id:fake
    32102     _Primitive-subtract-mem-from-xreg/imm32/next
    32103 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
    32104     0x11/imm32/alloc-id:fake:payload
    32105     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
    32106     0x11/imm32/alloc-id:fake
    32107     _string-subtract/imm32/name
    32108     0x11/imm32/alloc-id:fake
    32109     Single-float-var-in-mem/imm32/inouts
    32110     0x11/imm32/alloc-id:fake
    32111     Single-float-var-in-some-register/imm32/outputs
    32112     0x11/imm32/alloc-id:fake
    32113     _string_f3_0f_5c_subtract/imm32/subx-name
    32114     0/imm32/no-rm32
    32115     0/imm32/no-r32
    32116     0/imm32/no-imm32
    32117     0/imm32/no-imm8
    32118     0/imm32/no-disp32
    32119     1/imm32/xm32-is-first-inout
    32120     3/imm32/x32-is-first-output
    32121     0x11/imm32/alloc-id:fake
    32122     _Primitive-multiply-xreg-by-xreg/imm32/next
    32123 # - floating-point multiply
    32124 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
    32125     0x11/imm32/alloc-id:fake:payload
    32126     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
    32127     0x11/imm32/alloc-id:fake
    32128     _string-multiply/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-float-var-in-some-register/imm32/outputs
    32133     0x11/imm32/alloc-id:fake
    32134     _string_f3_0f_59_multiply/imm32/subx-name
    32135     0/imm32/no-rm32
    32136     0/imm32/no-r32
    32137     0/imm32/no-imm32
    32138     0/imm32/no-imm8
    32139     0/imm32/no-disp32
    32140     1/imm32/xm32-is-first-inout
    32141     3/imm32/x32-is-first-output
    32142     0x11/imm32/alloc-id:fake
    32143     _Primitive-multiply-xreg-by-mem/imm32/next
    32144 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
    32145     0x11/imm32/alloc-id:fake:payload
    32146     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
    32147     0x11/imm32/alloc-id:fake
    32148     _string-multiply/imm32/name
    32149     0x11/imm32/alloc-id:fake
    32150     Single-float-var-in-mem/imm32/inouts
    32151     0x11/imm32/alloc-id:fake
    32152     Single-float-var-in-some-register/imm32/outputs
    32153     0x11/imm32/alloc-id:fake
    32154     _string_f3_0f_59_multiply/imm32/subx-name
    32155     0/imm32/no-rm32
    32156     0/imm32/no-r32
    32157     0/imm32/no-imm32
    32158     0/imm32/no-imm8
    32159     0/imm32/no-disp32
    32160     1/imm32/xm32-is-first-inout
    32161     3/imm32/x32-is-first-output
    32162     0x11/imm32/alloc-id:fake
    32163     _Primitive-divide-xreg-by-xreg/imm32/next
    32164 # - floating-point divide
    32165 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
    32166     0x11/imm32/alloc-id:fake:payload
    32167     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32168     0x11/imm32/alloc-id:fake
    32169     _string-divide/imm32/name
    32170     0x11/imm32/alloc-id:fake
    32171     Single-float-var-in-some-register/imm32/inouts
    32172     0x11/imm32/alloc-id:fake
    32173     Single-float-var-in-some-register/imm32/outputs
    32174     0x11/imm32/alloc-id:fake
    32175     _string_f3_0f_5e_divide/imm32/subx-name
    32176     0/imm32/no-rm32
    32177     0/imm32/no-r32
    32178     0/imm32/no-imm32
    32179     0/imm32/no-imm8
    32180     0/imm32/no-disp32
    32181     1/imm32/xm32-is-first-inout
    32182     3/imm32/x32-is-first-output
    32183     0x11/imm32/alloc-id:fake
    32184     _Primitive-divide-xreg-by-mem/imm32/next
    32185 _Primitive-divide-xreg-by-mem:  # (payload primitive)
    32186     0x11/imm32/alloc-id:fake:payload
    32187     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32188     0x11/imm32/alloc-id:fake
    32189     _string-divide/imm32/name
    32190     0x11/imm32/alloc-id:fake
    32191     Single-float-var-in-mem/imm32/inouts
    32192     0x11/imm32/alloc-id:fake
    32193     Single-float-var-in-some-register/imm32/outputs
    32194     0x11/imm32/alloc-id:fake
    32195     _string_f3_0f_5e_divide/imm32/subx-name
    32196     0/imm32/no-rm32
    32197     0/imm32/no-r32
    32198     0/imm32/no-imm32
    32199     0/imm32/no-imm8
    32200     0/imm32/no-disp32
    32201     1/imm32/xm32-is-first-inout
    32202     3/imm32/x32-is-first-output
    32203     0x11/imm32/alloc-id:fake
    32204     _Primitive-max-xreg-with-xreg/imm32/next
    32205 # - floating-point maximum
    32206 _Primitive-max-xreg-with-xreg:  # (payload primitive)
    32207     0x11/imm32/alloc-id:fake:payload
    32208     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
    32209     0x11/imm32/alloc-id:fake
    32210     _string-max/imm32/name
    32211     0x11/imm32/alloc-id:fake
    32212     Single-float-var-in-some-register/imm32/inouts
    32213     0x11/imm32/alloc-id:fake
    32214     Single-float-var-in-some-register/imm32/outputs
    32215     0x11/imm32/alloc-id:fake
    32216     _string_f3_0f_5f_max/imm32/subx-name
    32217     0/imm32/no-rm32
    32218     0/imm32/no-r32
    32219     0/imm32/no-imm32
    32220     0/imm32/no-imm8
    32221     0/imm32/no-disp32
    32222     1/imm32/xm32-is-first-inout
    32223     3/imm32/x32-is-first-output
    32224     0x11/imm32/alloc-id:fake
    32225     _Primitive-max-xreg-with-mem/imm32/next
    32226 _Primitive-max-xreg-with-mem:  # (payload primitive)
    32227     0x11/imm32/alloc-id:fake:payload
    32228     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
    32229     0x11/imm32/alloc-id:fake
    32230     _string-max/imm32/name
    32231     0x11/imm32/alloc-id:fake
    32232     Single-float-var-in-mem/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_5f_max/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     1/imm32/xm32-is-first-inout
    32243     3/imm32/x32-is-first-output
    32244     0x11/imm32/alloc-id:fake
    32245     _Primitive-min-xreg-with-xreg/imm32/next
    32246 # - floating-point minimum
    32247 _Primitive-min-xreg-with-xreg:  # (payload primitive)
    32248     0x11/imm32/alloc-id:fake:payload
    32249     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32250     0x11/imm32/alloc-id:fake
    32251     _string-min/imm32/name
    32252     0x11/imm32/alloc-id:fake
    32253     Single-float-var-in-some-register/imm32/inouts
    32254     0x11/imm32/alloc-id:fake
    32255     Single-float-var-in-some-register/imm32/outputs
    32256     0x11/imm32/alloc-id:fake
    32257     _string_f3_0f_5d_min/imm32/subx-name
    32258     0/imm32/no-rm32
    32259     0/imm32/no-r32
    32260     0/imm32/no-imm32
    32261     0/imm32/no-imm8
    32262     0/imm32/no-disp32
    32263     1/imm32/xm32-is-first-inout
    32264     3/imm32/x32-is-first-output
    32265     0x11/imm32/alloc-id:fake
    32266     _Primitive-min-xreg-with-mem/imm32/next
    32267 _Primitive-min-xreg-with-mem:  # (payload primitive)
    32268     0x11/imm32/alloc-id:fake:payload
    32269     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32270     0x11/imm32/alloc-id:fake
    32271     _string-min/imm32/name
    32272     0x11/imm32/alloc-id:fake
    32273     Single-float-var-in-mem/imm32/inouts
    32274     0x11/imm32/alloc-id:fake
    32275     Single-float-var-in-some-register/imm32/outputs
    32276     0x11/imm32/alloc-id:fake
    32277     _string_f3_0f_5d_min/imm32/subx-name
    32278     0/imm32/no-rm32
    32279     0/imm32/no-r32
    32280     0/imm32/no-imm32
    32281     0/imm32/no-imm8
    32282     0/imm32/no-disp32
    32283     1/imm32/xm32-is-first-inout
    32284     3/imm32/x32-is-first-output
    32285     0x11/imm32/alloc-id:fake
    32286     _Primitive-reciprocal-xreg-to-xreg/imm32/next
    32287 # - floating-point reciprocal
    32288 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
    32289     0x11/imm32/alloc-id:fake:payload
    32290     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32291     0x11/imm32/alloc-id:fake
    32292     _string-reciprocal/imm32/name
    32293     0x11/imm32/alloc-id:fake
    32294     Single-float-var-in-some-register/imm32/inouts
    32295     0x11/imm32/alloc-id:fake
    32296     Single-float-var-in-some-register/imm32/outputs
    32297     0x11/imm32/alloc-id:fake
    32298     _string_f3_0f_53_reciprocal/imm32/subx-name
    32299     0/imm32/no-rm32
    32300     0/imm32/no-r32
    32301     0/imm32/no-imm32
    32302     0/imm32/no-imm8
    32303     0/imm32/no-disp32
    32304     1/imm32/xm32-is-first-inout
    32305     3/imm32/x32-is-first-output
    32306     0x11/imm32/alloc-id:fake
    32307     _Primitive-reciprocal-mem-to-xreg/imm32/next
    32308 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
    32309     0x11/imm32/alloc-id:fake:payload
    32310     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32311     0x11/imm32/alloc-id:fake
    32312     _string-reciprocal/imm32/name
    32313     0x11/imm32/alloc-id:fake
    32314     Single-float-var-in-mem/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_53_reciprocal/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-square-root-xreg-to-xreg/imm32/next
    32328 # - floating-point square root
    32329 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
    32330     0x11/imm32/alloc-id:fake:payload
    32331     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32332     0x11/imm32/alloc-id:fake
    32333     _string-square-root/imm32/name
    32334     0x11/imm32/alloc-id:fake
    32335     Single-float-var-in-some-register/imm32/inouts
    32336     0x11/imm32/alloc-id:fake
    32337     Single-float-var-in-some-register/imm32/outputs
    32338     0x11/imm32/alloc-id:fake
    32339     _string_f3_0f_51_square_root/imm32/subx-name
    32340     0/imm32/no-rm32
    32341     0/imm32/no-r32
    32342     0/imm32/no-imm32
    32343     0/imm32/no-imm8
    32344     0/imm32/no-disp32
    32345     1/imm32/xm32-is-first-inout
    32346     3/imm32/x32-is-first-output
    32347     0x11/imm32/alloc-id:fake
    32348     _Primitive-square-root-mem-to-xreg/imm32/next
    32349 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
    32350     0x11/imm32/alloc-id:fake:payload
    32351     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32352     0x11/imm32/alloc-id:fake
    32353     _string-square-root/imm32/name
    32354     0x11/imm32/alloc-id:fake
    32355     Single-float-var-in-mem/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_51_square_root/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-inverse-square-root-xreg-to-xreg/imm32/next
    32369 # - floating-point inverse square root 1/sqrt(x)
    32370 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
    32371     0x11/imm32/alloc-id:fake:payload
    32372     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32373     0x11/imm32/alloc-id:fake
    32374     _string-inverse-square-root/imm32/name
    32375     0x11/imm32/alloc-id:fake
    32376     Single-float-var-in-some-register/imm32/inouts
    32377     0x11/imm32/alloc-id:fake
    32378     Single-float-var-in-some-register/imm32/outputs
    32379     0x11/imm32/alloc-id:fake
    32380     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32381     0/imm32/no-rm32
    32382     0/imm32/no-r32
    32383     0/imm32/no-imm32
    32384     0/imm32/no-imm8
    32385     0/imm32/no-disp32
    32386     1/imm32/xm32-is-first-inout
    32387     3/imm32/x32-is-first-output
    32388     0x11/imm32/alloc-id:fake
    32389     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
    32390 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
    32391     0x11/imm32/alloc-id:fake:payload
    32392     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32393     0x11/imm32/alloc-id:fake
    32394     _string-inverse-square-root/imm32/name
    32395     0x11/imm32/alloc-id:fake
    32396     Single-float-var-in-mem/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_52_inverse_square_root/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-compare-xreg-with-xreg/imm32/next
    32410 # - floating-point compare
    32411 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
    32412     0x11/imm32/alloc-id:fake:payload
    32413     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
    32414     0x11/imm32/alloc-id:fake
    32415     _string-compare/imm32/name
    32416     0x11/imm32/alloc-id:fake
    32417     Two-float-args-in-regs/imm32/inouts
    32418     0/imm32/no-outputs
    32419     0/imm32/no-outputs
    32420     0x11/imm32/alloc-id:fake
    32421     _string_0f_2f_compare/imm32/subx-name
    32422     0/imm32/no-rm32
    32423     0/imm32/no-r32
    32424     0/imm32/no-imm32
    32425     0/imm32/no-imm8
    32426     0/imm32/no-disp32
    32427     2/imm32/xm32-is-second-inout
    32428     1/imm32/x32-is-first-inout
    32429     0x11/imm32/alloc-id:fake
    32430     _Primitive-compare-xreg-with-mem/imm32/next
    32431 _Primitive-compare-xreg-with-mem:  # (payload primitive)
    32432     0x11/imm32/alloc-id:fake:payload
    32433     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
    32434     0x11/imm32/alloc-id:fake
    32435     _string-compare/imm32/name
    32436     0x11/imm32/alloc-id:fake
    32437     Two-args-float-reg-float-stack/imm32/inouts
    32438     0/imm32/no-outputs
    32439     0/imm32/no-outputs
    32440     0x11/imm32/alloc-id:fake
    32441     _string_0f_2f_compare/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     2/imm32/xm32-is-second-inout
    32448     1/imm32/x32-is-first-inout
    32449     0x11/imm32/alloc-id:fake
    32450     _Primitive-break-if-addr</imm32/next
    32451 # - branches
    32452 _Primitive-break-if-addr<:  # (payload primitive)
    32453     0x11/imm32/alloc-id:fake:payload
    32454     0x11/imm32/alloc-id:fake
    32455     _string-break-if-addr</imm32/name
    32456     0/imm32/no-inouts
    32457     0/imm32/no-inouts
    32458     0/imm32/no-outputs
    32459     0/imm32/no-outputs
    32460     0x11/imm32/alloc-id:fake
    32461     _string_0f_82_jump_break/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     0/imm32/no-xm32
    32468     0/imm32/no-x32
    32469     0x11/imm32/alloc-id:fake
    32470     _Primitive-break-if-addr>=/imm32/next
    32471 _Primitive-break-if-addr>=:  # (payload primitive)
    32472     0x11/imm32/alloc-id:fake:payload
    32473     0x11/imm32/alloc-id:fake
    32474     _string-break-if-addr>=/imm32/name
    32475     0/imm32/no-inouts
    32476     0/imm32/no-inouts
    32477     0/imm32/no-outputs
    32478     0/imm32/no-outputs
    32479     0x11/imm32/alloc-id:fake
    32480     _string_0f_83_jump_break/imm32/subx-name
    32481     0/imm32/no-rm32
    32482     0/imm32/no-r32
    32483     0/imm32/no-imm32
    32484     0/imm32/no-imm8
    32485     0/imm32/no-disp32
    32486     0/imm32/no-xm32
    32487     0/imm32/no-x32
    32488     0x11/imm32/alloc-id:fake
    32489     _Primitive-break-if-=/imm32/next
    32490 _Primitive-break-if-=:  # (payload primitive)
    32491     0x11/imm32/alloc-id:fake:payload
    32492     0x11/imm32/alloc-id:fake
    32493     _string-break-if-=/imm32/name
    32494     0/imm32/no-inouts
    32495     0/imm32/no-inouts
    32496     0/imm32/no-outputs
    32497     0/imm32/no-outputs
    32498     0x11/imm32/alloc-id:fake
    32499     _string_0f_84_jump_break/imm32/subx-name
    32500     0/imm32/no-rm32
    32501     0/imm32/no-r32
    32502     0/imm32/no-imm32
    32503     0/imm32/no-imm8
    32504     0/imm32/no-disp32
    32505     0/imm32/no-xm32
    32506     0/imm32/no-x32
    32507     0x11/imm32/alloc-id:fake
    32508     _Primitive-break-if-!=/imm32/next
    32509 _Primitive-break-if-!=:  # (payload primitive)
    32510     0x11/imm32/alloc-id:fake:payload
    32511     0x11/imm32/alloc-id:fake
    32512     _string-break-if-!=/imm32/name
    32513     0/imm32/no-inouts
    32514     0/imm32/no-inouts
    32515     0/imm32/no-outputs
    32516     0/imm32/no-outputs
    32517     0x11/imm32/alloc-id:fake
    32518     _string_0f_85_jump_break/imm32/subx-name
    32519     0/imm32/no-rm32
    32520     0/imm32/no-r32
    32521     0/imm32/no-imm32
    32522     0/imm32/no-imm8
    32523     0/imm32/no-disp32
    32524     0/imm32/no-xm32
    32525     0/imm32/no-x32
    32526     0x11/imm32/alloc-id:fake
    32527     _Primitive-break-if-addr<=/imm32/next
    32528 _Primitive-break-if-addr<=:  # (payload primitive)
    32529     0x11/imm32/alloc-id:fake:payload
    32530     0x11/imm32/alloc-id:fake
    32531     _string-break-if-addr<=/imm32/name
    32532     0/imm32/no-inouts
    32533     0/imm32/no-inouts
    32534     0/imm32/no-outputs
    32535     0/imm32/no-outputs
    32536     0x11/imm32/alloc-id:fake
    32537     _string_0f_86_jump_break/imm32/subx-name
    32538     0/imm32/no-rm32
    32539     0/imm32/no-r32
    32540     0/imm32/no-imm32
    32541     0/imm32/no-imm8
    32542     0/imm32/no-disp32
    32543     0/imm32/no-xm32
    32544     0/imm32/no-x32
    32545     0x11/imm32/alloc-id:fake
    32546     _Primitive-break-if-addr>/imm32/next
    32547 _Primitive-break-if-addr>:  # (payload primitive)
    32548     0x11/imm32/alloc-id:fake:payload
    32549     0x11/imm32/alloc-id:fake
    32550     _string-break-if-addr>/imm32/name
    32551     0/imm32/no-inouts
    32552     0/imm32/no-inouts
    32553     0/imm32/no-outputs
    32554     0/imm32/no-outputs
    32555     0x11/imm32/alloc-id:fake
    32556     _string_0f_87_jump_break/imm32/subx-name
    32557     0/imm32/no-rm32
    32558     0/imm32/no-r32
    32559     0/imm32/no-imm32
    32560     0/imm32/no-imm8
    32561     0/imm32/no-disp32
    32562     0/imm32/no-xm32
    32563     0/imm32/no-x32
    32564     0x11/imm32/alloc-id:fake
    32565     _Primitive-break-if-</imm32/next
    32566 _Primitive-break-if-<:  # (payload primitive)
    32567     0x11/imm32/alloc-id:fake:payload
    32568     0x11/imm32/alloc-id:fake
    32569     _string-break-if-</imm32/name
    32570     0/imm32/no-inouts
    32571     0/imm32/no-inouts
    32572     0/imm32/no-outputs
    32573     0/imm32/no-outputs
    32574     0x11/imm32/alloc-id:fake
    32575     _string_0f_8c_jump_break/imm32/subx-name
    32576     0/imm32/no-rm32
    32577     0/imm32/no-r32
    32578     0/imm32/no-imm32
    32579     0/imm32/no-imm8
    32580     0/imm32/no-disp32
    32581     0/imm32/no-xm32
    32582     0/imm32/no-x32
    32583     0x11/imm32/alloc-id:fake
    32584     _Primitive-break-if->=/imm32/next
    32585 _Primitive-break-if->=:  # (payload primitive)
    32586     0x11/imm32/alloc-id:fake:payload
    32587     0x11/imm32/alloc-id:fake
    32588     _string-break-if->=/imm32/name
    32589     0/imm32/no-inouts
    32590     0/imm32/no-inouts
    32591     0/imm32/no-outputs
    32592     0/imm32/no-outputs
    32593     0x11/imm32/alloc-id:fake
    32594     _string_0f_8d_jump_break/imm32/subx-name
    32595     0/imm32/no-rm32
    32596     0/imm32/no-r32
    32597     0/imm32/no-imm32
    32598     0/imm32/no-imm8
    32599     0/imm32/no-disp32
    32600     0/imm32/no-xm32
    32601     0/imm32/no-x32
    32602     0x11/imm32/alloc-id:fake
    32603     _Primitive-break-if-<=/imm32/next
    32604 _Primitive-break-if-<=:  # (payload primitive)
    32605     0x11/imm32/alloc-id:fake:payload
    32606     0x11/imm32/alloc-id:fake
    32607     _string-break-if-<=/imm32/name
    32608     0/imm32/no-inouts
    32609     0/imm32/no-inouts
    32610     0/imm32/no-outputs
    32611     0/imm32/no-outputs
    32612     0x11/imm32/alloc-id:fake
    32613     _string_0f_8e_jump_break/imm32/subx-name
    32614     0/imm32/no-rm32
    32615     0/imm32/no-r32
    32616     0/imm32/no-imm32
    32617     0/imm32/no-imm8
    32618     0/imm32/no-disp32
    32619     0/imm32/no-xm32
    32620     0/imm32/no-x32
    32621     0x11/imm32/alloc-id:fake
    32622     _Primitive-break-if->/imm32/next
    32623 _Primitive-break-if->:  # (payload primitive)
    32624     0x11/imm32/alloc-id:fake:payload
    32625     0x11/imm32/alloc-id:fake
    32626     _string-break-if->/imm32/name
    32627     0/imm32/no-inouts
    32628     0/imm32/no-inouts
    32629     0/imm32/no-outputs
    32630     0/imm32/no-outputs
    32631     0x11/imm32/alloc-id:fake
    32632     _string_0f_8f_jump_break/imm32/subx-name
    32633     0/imm32/no-rm32
    32634     0/imm32/no-r32
    32635     0/imm32/no-imm32
    32636     0/imm32/no-imm8
    32637     0/imm32/no-disp32
    32638     0/imm32/no-xm32
    32639     0/imm32/no-x32
    32640     0x11/imm32/alloc-id:fake
    32641     _Primitive-break/imm32/next
    32642 _Primitive-break:  # (payload primitive)
    32643     0x11/imm32/alloc-id:fake:payload
    32644     0x11/imm32/alloc-id:fake
    32645     _string-break/imm32/name
    32646     0/imm32/no-inouts
    32647     0/imm32/no-inouts
    32648     0/imm32/no-outputs
    32649     0/imm32/no-outputs
    32650     0x11/imm32/alloc-id:fake
    32651     _string_e9_jump_break/imm32/subx-name
    32652     0/imm32/no-rm32
    32653     0/imm32/no-r32
    32654     0/imm32/no-imm32
    32655     0/imm32/no-imm8
    32656     0/imm32/no-disp32
    32657     0/imm32/no-xm32
    32658     0/imm32/no-x32
    32659     0x11/imm32/alloc-id:fake
    32660     _Primitive-loop-if-addr</imm32/next
    32661 _Primitive-loop-if-addr<:  # (payload primitive)
    32662     0x11/imm32/alloc-id:fake:payload
    32663     0x11/imm32/alloc-id:fake
    32664     _string-loop-if-addr</imm32/name
    32665     0/imm32/no-inouts
    32666     0/imm32/no-inouts
    32667     0/imm32/no-outputs
    32668     0/imm32/no-outputs
    32669     0x11/imm32/alloc-id:fake
    32670     _string_0f_82_jump_loop/imm32/subx-name
    32671     0/imm32/no-rm32
    32672     0/imm32/no-r32
    32673     0/imm32/no-imm32
    32674     0/imm32/no-imm8
    32675     0/imm32/no-disp32
    32676     0/imm32/no-xm32
    32677     0/imm32/no-x32
    32678     0x11/imm32/alloc-id:fake
    32679     _Primitive-loop-if-addr>=/imm32/next
    32680 _Primitive-loop-if-addr>=:  # (payload primitive)
    32681     0x11/imm32/alloc-id:fake:payload
    32682     0x11/imm32/alloc-id:fake
    32683     _string-loop-if-addr>=/imm32/name
    32684     0/imm32/no-inouts
    32685     0/imm32/no-inouts
    32686     0/imm32/no-outputs
    32687     0/imm32/no-outputs
    32688     0x11/imm32/alloc-id:fake
    32689     _string_0f_83_jump_loop/imm32/subx-name
    32690     0/imm32/no-rm32
    32691     0/imm32/no-r32
    32692     0/imm32/no-imm32
    32693     0/imm32/no-imm8
    32694     0/imm32/no-disp32
    32695     0/imm32/no-xm32
    32696     0/imm32/no-x32
    32697     0x11/imm32/alloc-id:fake
    32698     _Primitive-loop-if-=/imm32/next
    32699 _Primitive-loop-if-=:  # (payload primitive)
    32700     0x11/imm32/alloc-id:fake:payload
    32701     0x11/imm32/alloc-id:fake
    32702     _string-loop-if-=/imm32/name
    32703     0/imm32/no-inouts
    32704     0/imm32/no-inouts
    32705     0/imm32/no-outputs
    32706     0/imm32/no-outputs
    32707     0x11/imm32/alloc-id:fake
    32708     _string_0f_84_jump_loop/imm32/subx-name
    32709     0/imm32/no-rm32
    32710     0/imm32/no-r32
    32711     0/imm32/no-imm32
    32712     0/imm32/no-imm8
    32713     0/imm32/no-disp32
    32714     0/imm32/no-xm32
    32715     0/imm32/no-x32
    32716     0x11/imm32/alloc-id:fake
    32717     _Primitive-loop-if-!=/imm32/next
    32718 _Primitive-loop-if-!=:  # (payload primitive)
    32719     0x11/imm32/alloc-id:fake:payload
    32720     0x11/imm32/alloc-id:fake
    32721     _string-loop-if-!=/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_85_jump_loop/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-loop-if-addr<=/imm32/next
    32737 _Primitive-loop-if-addr<=:  # (payload primitive)
    32738     0x11/imm32/alloc-id:fake:payload
    32739     0x11/imm32/alloc-id:fake
    32740     _string-loop-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_86_jump_loop/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-loop-if-addr>/imm32/next
    32756 _Primitive-loop-if-addr>:  # (payload primitive)
    32757     0x11/imm32/alloc-id:fake:payload
    32758     0x11/imm32/alloc-id:fake
    32759     _string-loop-if-addr>/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_87_jump_loop/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-loop-if-</imm32/next
    32775 _Primitive-loop-if-<:  # (payload primitive)
    32776     0x11/imm32/alloc-id:fake:payload
    32777     0x11/imm32/alloc-id:fake
    32778     _string-loop-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_8c_jump_loop/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-loop-if->=/imm32/next
    32794 _Primitive-loop-if->=:  # (payload primitive)
    32795     0x11/imm32/alloc-id:fake:payload
    32796     0x11/imm32/alloc-id:fake
    32797     _string-loop-if->=/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_8d_jump_loop/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-loop-if-<=/imm32/next
    32813 _Primitive-loop-if-<=:  # (payload primitive)
    32814     0x11/imm32/alloc-id:fake:payload
    32815     0x11/imm32/alloc-id:fake
    32816     _string-loop-if-<=/imm32/name
    32817     0/imm32/no-inouts
    32818     0/imm32/no-inouts
    32819     0/imm32/no-outputs
    32820     0/imm32/no-outputs
    32821     0x11/imm32/alloc-id:fake
    32822     _string_0f_8e_jump_loop/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-loop-if->/imm32/next
    32832 _Primitive-loop-if->:  # (payload primitive)
    32833     0x11/imm32/alloc-id:fake:payload
    32834     0x11/imm32/alloc-id:fake
    32835     _string-loop-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_8f_jump_loop/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-loop/imm32/next  # we probably don't need an unconditional break
    32851 _Primitive-loop:  # (payload primitive)
    32852     0x11/imm32/alloc-id:fake:payload
    32853     0x11/imm32/alloc-id:fake
    32854     _string-loop/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_e9_jump_loop/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-addr<-named/imm32/next
    32870 # - branches to named blocks
    32871 _Primitive-break-if-addr<-named:  # (payload primitive)
    32872     0x11/imm32/alloc-id:fake:payload
    32873     0x11/imm32/alloc-id:fake
    32874     _string-break-if-addr</imm32/name
    32875     0x11/imm32/alloc-id:fake
    32876     Single-lit-var/imm32/inouts
    32877     0/imm32/no-outputs
    32878     0/imm32/no-outputs
    32879     0x11/imm32/alloc-id:fake
    32880     _string_0f_82_jump_label/imm32/subx-name
    32881     0/imm32/no-rm32
    32882     0/imm32/no-r32
    32883     0/imm32/no-imm32
    32884     0/imm32/no-imm8
    32885     1/imm32/disp32-is-first-inout
    32886     0/imm32/no-xm32
    32887     0/imm32/no-x32
    32888     0x11/imm32/alloc-id:fake
    32889     _Primitive-break-if-addr>=-named/imm32/next
    32890 _Primitive-break-if-addr>=-named:  # (payload primitive)
    32891     0x11/imm32/alloc-id:fake:payload
    32892     0x11/imm32/alloc-id:fake
    32893     _string-break-if-addr>=/imm32/name
    32894     0x11/imm32/alloc-id:fake
    32895     Single-lit-var/imm32/inouts
    32896     0/imm32/no-outputs
    32897     0/imm32/no-outputs
    32898     0x11/imm32/alloc-id:fake
    32899     _string_0f_83_jump_label/imm32/subx-name
    32900     0/imm32/no-rm32
    32901     0/imm32/no-r32
    32902     0/imm32/no-imm32
    32903     0/imm32/no-imm8
    32904     1/imm32/disp32-is-first-inout
    32905     0/imm32/no-xm32
    32906     0/imm32/no-x32
    32907     0x11/imm32/alloc-id:fake
    32908     _Primitive-break-if-=-named/imm32/next
    32909 _Primitive-break-if-=-named:  # (payload primitive)
    32910     0x11/imm32/alloc-id:fake:payload
    32911     0x11/imm32/alloc-id:fake
    32912     _string-break-if-=/imm32/name
    32913     0x11/imm32/alloc-id:fake
    32914     Single-lit-var/imm32/inouts
    32915     0/imm32/no-outputs
    32916     0/imm32/no-outputs
    32917     0x11/imm32/alloc-id:fake
    32918     _string_0f_84_jump_label/imm32/subx-name
    32919     0/imm32/no-rm32
    32920     0/imm32/no-r32
    32921     0/imm32/no-imm32
    32922     0/imm32/no-imm8
    32923     1/imm32/disp32-is-first-inout
    32924     0/imm32/no-xm32
    32925     0/imm32/no-x32
    32926     0x11/imm32/alloc-id:fake
    32927     _Primitive-break-if-!=-named/imm32/next
    32928 _Primitive-break-if-!=-named:  # (payload primitive)
    32929     0x11/imm32/alloc-id:fake:payload
    32930     0x11/imm32/alloc-id:fake
    32931     _string-break-if-!=/imm32/name
    32932     0x11/imm32/alloc-id:fake
    32933     Single-lit-var/imm32/inouts
    32934     0/imm32/no-outputs
    32935     0/imm32/no-outputs
    32936     0x11/imm32/alloc-id:fake
    32937     _string_0f_85_jump_label/imm32/subx-name
    32938     0/imm32/no-rm32
    32939     0/imm32/no-r32
    32940     0/imm32/no-imm32
    32941     0/imm32/no-imm8
    32942     1/imm32/disp32-is-first-inout
    32943     0/imm32/no-xm32
    32944     0/imm32/no-x32
    32945     0x11/imm32/alloc-id:fake
    32946     _Primitive-break-if-addr<=-named/imm32/next
    32947 _Primitive-break-if-addr<=-named:  # (payload primitive)
    32948     0x11/imm32/alloc-id:fake:payload
    32949     0x11/imm32/alloc-id:fake
    32950     _string-break-if-addr<=/imm32/name
    32951     0x11/imm32/alloc-id:fake
    32952     Single-lit-var/imm32/inouts
    32953     0/imm32/no-outputs
    32954     0/imm32/no-outputs
    32955     0x11/imm32/alloc-id:fake
    32956     _string_0f_86_jump_label/imm32/subx-name
    32957     0/imm32/no-rm32
    32958     0/imm32/no-r32
    32959     0/imm32/no-imm32
    32960     0/imm32/no-imm8
    32961     1/imm32/disp32-is-first-inout
    32962     0/imm32/no-xm32
    32963     0/imm32/no-x32
    32964     0x11/imm32/alloc-id:fake
    32965     _Primitive-break-if-addr>-named/imm32/next
    32966 _Primitive-break-if-addr>-named:  # (payload primitive)
    32967     0x11/imm32/alloc-id:fake:payload
    32968     0x11/imm32/alloc-id:fake
    32969     _string-break-if-addr>/imm32/name
    32970     0x11/imm32/alloc-id:fake
    32971     Single-lit-var/imm32/inouts
    32972     0/imm32/no-outputs
    32973     0/imm32/no-outputs
    32974     0x11/imm32/alloc-id:fake
    32975     _string_0f_87_jump_label/imm32/subx-name
    32976     0/imm32/no-rm32
    32977     0/imm32/no-r32
    32978     0/imm32/no-imm32
    32979     0/imm32/no-imm8
    32980     1/imm32/disp32-is-first-inout
    32981     0/imm32/no-xm32
    32982     0/imm32/no-x32
    32983     0x11/imm32/alloc-id:fake
    32984     _Primitive-break-if-<-named/imm32/next
    32985 _Primitive-break-if-<-named:  # (payload primitive)
    32986     0x11/imm32/alloc-id:fake:payload
    32987     0x11/imm32/alloc-id:fake
    32988     _string-break-if-</imm32/name
    32989     0x11/imm32/alloc-id:fake
    32990     Single-lit-var/imm32/inouts
    32991     0/imm32/no-outputs
    32992     0/imm32/no-outputs
    32993     0x11/imm32/alloc-id:fake
    32994     _string_0f_8c_jump_label/imm32/subx-name
    32995     0/imm32/no-rm32
    32996     0/imm32/no-r32
    32997     0/imm32/no-imm32
    32998     0/imm32/no-imm8
    32999     1/imm32/disp32-is-first-inout
    33000     0/imm32/no-xm32
    33001     0/imm32/no-x32
    33002     0x11/imm32/alloc-id:fake
    33003     _Primitive-break-if->=-named/imm32/next
    33004 _Primitive-break-if->=-named:  # (payload primitive)
    33005     0x11/imm32/alloc-id:fake:payload
    33006     0x11/imm32/alloc-id:fake
    33007     _string-break-if->=/imm32/name
    33008     0x11/imm32/alloc-id:fake
    33009     Single-lit-var/imm32/inouts
    33010     0/imm32/no-outputs
    33011     0/imm32/no-outputs
    33012     0x11/imm32/alloc-id:fake
    33013     _string_0f_8d_jump_label/imm32/subx-name
    33014     0/imm32/no-rm32
    33015     0/imm32/no-r32
    33016     0/imm32/no-imm32
    33017     0/imm32/no-imm8
    33018     1/imm32/disp32-is-first-inout
    33019     0/imm32/no-xm32
    33020     0/imm32/no-x32
    33021     0x11/imm32/alloc-id:fake
    33022     _Primitive-break-if-<=-named/imm32/next
    33023 _Primitive-break-if-<=-named:  # (payload primitive)
    33024     0x11/imm32/alloc-id:fake:payload
    33025     0x11/imm32/alloc-id:fake
    33026     _string-break-if-<=/imm32/name
    33027     0x11/imm32/alloc-id:fake
    33028     Single-lit-var/imm32/inouts
    33029     0/imm32/no-outputs
    33030     0/imm32/no-outputs
    33031     0x11/imm32/alloc-id:fake
    33032     _string_0f_8e_jump_label/imm32/subx-name
    33033     0/imm32/no-rm32
    33034     0/imm32/no-r32
    33035     0/imm32/no-imm32
    33036     0/imm32/no-imm8
    33037     1/imm32/disp32-is-first-inout
    33038     0/imm32/no-xm32
    33039     0/imm32/no-x32
    33040     0x11/imm32/alloc-id:fake
    33041     _Primitive-break-if->-named/imm32/next
    33042 _Primitive-break-if->-named:  # (payload primitive)
    33043     0x11/imm32/alloc-id:fake:payload
    33044     0x11/imm32/alloc-id:fake
    33045     _string-break-if->/imm32/name
    33046     0x11/imm32/alloc-id:fake
    33047     Single-lit-var/imm32/inouts
    33048     0/imm32/no-outputs
    33049     0/imm32/no-outputs
    33050     0x11/imm32/alloc-id:fake
    33051     _string_0f_8f_jump_label/imm32/subx-name
    33052     0/imm32/no-rm32
    33053     0/imm32/no-r32
    33054     0/imm32/no-imm32
    33055     0/imm32/no-imm8
    33056     1/imm32/disp32-is-first-inout
    33057     0/imm32/no-xm32
    33058     0/imm32/no-x32
    33059     0x11/imm32/alloc-id:fake
    33060     _Primitive-break-named/imm32/next
    33061 _Primitive-break-named:  # (payload primitive)
    33062     0x11/imm32/alloc-id:fake:payload
    33063     0x11/imm32/alloc-id:fake
    33064     _string-break/imm32/name
    33065     0x11/imm32/alloc-id:fake
    33066     Single-lit-var/imm32/inouts
    33067     0/imm32/no-outputs
    33068     0/imm32/no-outputs
    33069     0x11/imm32/alloc-id:fake
    33070     _string_e9_jump_label/imm32/subx-name
    33071     0/imm32/no-rm32
    33072     0/imm32/no-r32
    33073     0/imm32/no-imm32
    33074     0/imm32/no-imm8
    33075     1/imm32/disp32-is-first-inout
    33076     0/imm32/no-xm32
    33077     0/imm32/no-x32
    33078     0x11/imm32/alloc-id:fake
    33079     _Primitive-loop-if-addr<-named/imm32/next
    33080 _Primitive-loop-if-addr<-named:  # (payload primitive)
    33081     0x11/imm32/alloc-id:fake:payload
    33082     0x11/imm32/alloc-id:fake
    33083     _string-loop-if-addr</imm32/name
    33084     0x11/imm32/alloc-id:fake
    33085     Single-lit-var/imm32/inouts
    33086     0/imm32/no-outputs
    33087     0/imm32/no-outputs
    33088     0x11/imm32/alloc-id:fake
    33089     _string_0f_82_jump_label/imm32/subx-name
    33090     0/imm32/no-rm32
    33091     0/imm32/no-r32
    33092     0/imm32/no-imm32
    33093     0/imm32/no-imm8
    33094     1/imm32/disp32-is-first-inout
    33095     0/imm32/no-xm32
    33096     0/imm32/no-x32
    33097     0x11/imm32/alloc-id:fake
    33098     _Primitive-loop-if-addr>=-named/imm32/next
    33099 _Primitive-loop-if-addr>=-named:  # (payload primitive)
    33100     0x11/imm32/alloc-id:fake:payload
    33101     0x11/imm32/alloc-id:fake
    33102     _string-loop-if-addr>=/imm32/name
    33103     0x11/imm32/alloc-id:fake
    33104     Single-lit-var/imm32/inouts
    33105     0/imm32/no-outputs
    33106     0/imm32/no-outputs
    33107     0x11/imm32/alloc-id:fake
    33108     _string_0f_83_jump_label/imm32/subx-name
    33109     0/imm32/no-rm32
    33110     0/imm32/no-r32
    33111     0/imm32/no-imm32
    33112     0/imm32/no-imm8
    33113     1/imm32/disp32-is-first-inout
    33114     0/imm32/no-xm32
    33115     0/imm32/no-x32
    33116     0x11/imm32/alloc-id:fake
    33117     _Primitive-loop-if-=-named/imm32/next
    33118 _Primitive-loop-if-=-named:  # (payload primitive)
    33119     0x11/imm32/alloc-id:fake:payload
    33120     0x11/imm32/alloc-id:fake
    33121     _string-loop-if-=/imm32/name
    33122     0x11/imm32/alloc-id:fake
    33123     Single-lit-var/imm32/inouts
    33124     0/imm32/no-outputs
    33125     0/imm32/no-outputs
    33126     0x11/imm32/alloc-id:fake
    33127     _string_0f_84_jump_label/imm32/subx-name
    33128     0/imm32/no-rm32
    33129     0/imm32/no-r32
    33130     0/imm32/no-imm32
    33131     0/imm32/no-imm8
    33132     1/imm32/disp32-is-first-inout
    33133     0/imm32/no-xm32
    33134     0/imm32/no-x32
    33135     0x11/imm32/alloc-id:fake
    33136     _Primitive-loop-if-!=-named/imm32/next
    33137 _Primitive-loop-if-!=-named:  # (payload primitive)
    33138     0x11/imm32/alloc-id:fake:payload
    33139     0x11/imm32/alloc-id:fake
    33140     _string-loop-if-!=/imm32/name
    33141     0x11/imm32/alloc-id:fake
    33142     Single-lit-var/imm32/inouts
    33143     0/imm32/no-outputs
    33144     0/imm32/no-outputs
    33145     0x11/imm32/alloc-id:fake
    33146     _string_0f_85_jump_label/imm32/subx-name
    33147     0/imm32/no-rm32
    33148     0/imm32/no-r32
    33149     0/imm32/no-imm32
    33150     0/imm32/no-imm8
    33151     1/imm32/disp32-is-first-inout
    33152     0/imm32/no-xm32
    33153     0/imm32/no-x32
    33154     0x11/imm32/alloc-id:fake
    33155     _Primitive-loop-if-addr<=-named/imm32/next
    33156 _Primitive-loop-if-addr<=-named:  # (payload primitive)
    33157     0x11/imm32/alloc-id:fake:payload
    33158     0x11/imm32/alloc-id:fake
    33159     _string-loop-if-addr<=/imm32/name
    33160     0x11/imm32/alloc-id:fake
    33161     Single-lit-var/imm32/inouts
    33162     0/imm32/no-outputs
    33163     0/imm32/no-outputs
    33164     0x11/imm32/alloc-id:fake
    33165     _string_0f_86_jump_label/imm32/subx-name
    33166     0/imm32/no-rm32
    33167     0/imm32/no-r32
    33168     0/imm32/no-imm32
    33169     0/imm32/no-imm8
    33170     1/imm32/disp32-is-first-inout
    33171     0/imm32/no-xm32
    33172     0/imm32/no-x32
    33173     0x11/imm32/alloc-id:fake
    33174     _Primitive-loop-if-addr>-named/imm32/next
    33175 _Primitive-loop-if-addr>-named:  # (payload primitive)
    33176     0x11/imm32/alloc-id:fake:payload
    33177     0x11/imm32/alloc-id:fake
    33178     _string-loop-if-addr>/imm32/name
    33179     0x11/imm32/alloc-id:fake
    33180     Single-lit-var/imm32/inouts
    33181     0/imm32/no-outputs
    33182     0/imm32/no-outputs
    33183     0x11/imm32/alloc-id:fake
    33184     _string_0f_87_jump_label/imm32/subx-name
    33185     0/imm32/no-rm32
    33186     0/imm32/no-r32
    33187     0/imm32/no-imm32
    33188     0/imm32/no-imm8
    33189     1/imm32/disp32-is-first-inout
    33190     0/imm32/no-xm32
    33191     0/imm32/no-x32
    33192     0x11/imm32/alloc-id:fake
    33193     _Primitive-loop-if-<-named/imm32/next
    33194 _Primitive-loop-if-<-named:  # (payload primitive)
    33195     0x11/imm32/alloc-id:fake:payload
    33196     0x11/imm32/alloc-id:fake
    33197     _string-loop-if-</imm32/name
    33198     0x11/imm32/alloc-id:fake
    33199     Single-lit-var/imm32/inouts
    33200     0/imm32/no-outputs
    33201     0/imm32/no-outputs
    33202     0x11/imm32/alloc-id:fake
    33203     _string_0f_8c_jump_label/imm32/subx-name
    33204     0/imm32/no-rm32
    33205     0/imm32/no-r32
    33206     0/imm32/no-imm32
    33207     0/imm32/no-imm8
    33208     1/imm32/disp32-is-first-inout
    33209     0/imm32/no-xm32
    33210     0/imm32/no-x32
    33211     0x11/imm32/alloc-id:fake
    33212     _Primitive-loop-if->=-named/imm32/next
    33213 _Primitive-loop-if->=-named:  # (payload primitive)
    33214     0x11/imm32/alloc-id:fake:payload
    33215     0x11/imm32/alloc-id:fake
    33216     _string-loop-if->=/imm32/name
    33217     0x11/imm32/alloc-id:fake
    33218     Single-lit-var/imm32/inouts
    33219     0/imm32/no-outputs
    33220     0/imm32/no-outputs
    33221     0x11/imm32/alloc-id:fake
    33222     _string_0f_8d_jump_label/imm32/subx-name
    33223     0/imm32/no-rm32
    33224     0/imm32/no-r32
    33225     0/imm32/no-imm32
    33226     0/imm32/no-imm8
    33227     1/imm32/disp32-is-first-inout
    33228     0/imm32/no-xm32
    33229     0/imm32/no-x32
    33230     0x11/imm32/alloc-id:fake
    33231     _Primitive-loop-if-<=-named/imm32/next
    33232 _Primitive-loop-if-<=-named:  # (payload primitive)
    33233     0x11/imm32/alloc-id:fake:payload
    33234     0x11/imm32/alloc-id:fake
    33235     _string-loop-if-<=/imm32/name
    33236     0x11/imm32/alloc-id:fake
    33237     Single-lit-var/imm32/inouts
    33238     0/imm32/no-outputs
    33239     0/imm32/no-outputs
    33240     0x11/imm32/alloc-id:fake
    33241     _string_0f_8e_jump_label/imm32/subx-name
    33242     0/imm32/no-rm32
    33243     0/imm32/no-r32
    33244     0/imm32/no-imm32
    33245     0/imm32/no-imm8
    33246     1/imm32/disp32-is-first-inout
    33247     0/imm32/no-xm32
    33248     0/imm32/no-x32
    33249     0x11/imm32/alloc-id:fake
    33250     _Primitive-loop-if->-named/imm32/next
    33251 _Primitive-loop-if->-named:  # (payload primitive)
    33252     0x11/imm32/alloc-id:fake:payload
    33253     0x11/imm32/alloc-id:fake
    33254     _string-loop-if->/imm32/name
    33255     0x11/imm32/alloc-id:fake
    33256     Single-lit-var/imm32/inouts
    33257     0/imm32/no-outputs
    33258     0/imm32/no-outputs
    33259     0x11/imm32/alloc-id:fake
    33260     _string_0f_8f_jump_label/imm32/subx-name
    33261     0/imm32/no-rm32
    33262     0/imm32/no-r32
    33263     0/imm32/no-imm32
    33264     0/imm32/no-imm8
    33265     1/imm32/disp32-is-first-inout
    33266     0/imm32/no-xm32
    33267     0/imm32/no-x32
    33268     0x11/imm32/alloc-id:fake
    33269     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
    33270 _Primitive-loop-named:  # (payload primitive)
    33271     0x11/imm32/alloc-id:fake:payload
    33272     0x11/imm32/alloc-id:fake
    33273     _string-loop/imm32/name
    33274     0x11/imm32/alloc-id:fake
    33275     Single-lit-var/imm32/inouts
    33276     0/imm32/no-outputs
    33277     0/imm32/no-outputs
    33278     0x11/imm32/alloc-id:fake
    33279     _string_e9_jump_label/imm32/subx-name
    33280     0/imm32/no-rm32
    33281     0/imm32/no-r32
    33282     0/imm32/no-imm32
    33283     0/imm32/no-imm8
    33284     1/imm32/disp32-is-first-inout
    33285     0/imm32/no-xm32
    33286     0/imm32/no-x32
    33287     0x11/imm32/alloc-id:fake
    33288     _Primitive-break-if-float</imm32/next
    33289 # - branches based on floating-point comparisons
    33290 _Primitive-break-if-float<:  # (payload primitive)
    33291     0x11/imm32/alloc-id:fake:payload
    33292     0x11/imm32/alloc-id:fake
    33293     _string-break-if-float</imm32/name
    33294     0/imm32/no-inouts
    33295     0/imm32/no-inouts
    33296     0/imm32/no-outputs
    33297     0/imm32/no-outputs
    33298     0x11/imm32/alloc-id:fake
    33299     _string_0f_82_jump_break/imm32/subx-name
    33300     0/imm32/no-rm32
    33301     0/imm32/no-r32
    33302     0/imm32/no-imm32
    33303     0/imm32/no-imm8
    33304     0/imm32/no-disp32
    33305     0/imm32/no-xm32
    33306     0/imm32/no-x32
    33307     0x11/imm32/alloc-id:fake
    33308     _Primitive-break-if-float>=/imm32/next
    33309 _Primitive-break-if-float>=:  # (payload primitive)
    33310     0x11/imm32/alloc-id:fake:payload
    33311     0x11/imm32/alloc-id:fake
    33312     _string-break-if-float>=/imm32/name
    33313     0/imm32/no-inouts
    33314     0/imm32/no-inouts
    33315     0/imm32/no-outputs
    33316     0/imm32/no-outputs
    33317     0x11/imm32/alloc-id:fake
    33318     _string_0f_83_jump_break/imm32/subx-name
    33319     0/imm32/no-rm32
    33320     0/imm32/no-r32
    33321     0/imm32/no-imm32
    33322     0/imm32/no-imm8
    33323     0/imm32/no-disp32
    33324     0/imm32/no-xm32
    33325     0/imm32/no-x32
    33326     0x11/imm32/alloc-id:fake
    33327     _Primitive-break-if-float<=/imm32/next
    33328 _Primitive-break-if-float<=:  # (payload primitive)
    33329     0x11/imm32/alloc-id:fake:payload
    33330     0x11/imm32/alloc-id:fake
    33331     _string-break-if-float<=/imm32/name
    33332     0/imm32/no-inouts
    33333     0/imm32/no-inouts
    33334     0/imm32/no-outputs
    33335     0/imm32/no-outputs
    33336     0x11/imm32/alloc-id:fake
    33337     _string_0f_86_jump_break/imm32/subx-name
    33338     0/imm32/no-rm32
    33339     0/imm32/no-r32
    33340     0/imm32/no-imm32
    33341     0/imm32/no-imm8
    33342     0/imm32/no-disp32
    33343     0/imm32/no-xm32
    33344     0/imm32/no-x32
    33345     0x11/imm32/alloc-id:fake
    33346     _Primitive-break-if-float>/imm32/next
    33347 _Primitive-break-if-float>:  # (payload primitive)
    33348     0x11/imm32/alloc-id:fake:payload
    33349     0x11/imm32/alloc-id:fake
    33350     _string-break-if-float>/imm32/name
    33351     0/imm32/no-inouts
    33352     0/imm32/no-inouts
    33353     0/imm32/no-outputs
    33354     0/imm32/no-outputs
    33355     0x11/imm32/alloc-id:fake
    33356     _string_0f_87_jump_break/imm32/subx-name
    33357     0/imm32/no-rm32
    33358     0/imm32/no-r32
    33359     0/imm32/no-imm32
    33360     0/imm32/no-imm8
    33361     0/imm32/no-disp32
    33362     0/imm32/no-xm32
    33363     0/imm32/no-x32
    33364     0x11/imm32/alloc-id:fake
    33365     _Primitive-loop-if-float</imm32/next
    33366 _Primitive-loop-if-float<:  # (payload primitive)
    33367     0x11/imm32/alloc-id:fake:payload
    33368     0x11/imm32/alloc-id:fake
    33369     _string-loop-if-float</imm32/name
    33370     0/imm32/no-inouts
    33371     0/imm32/no-inouts
    33372     0/imm32/no-outputs
    33373     0/imm32/no-outputs
    33374     0x11/imm32/alloc-id:fake
    33375     _string_0f_82_jump_loop/imm32/subx-name
    33376     0/imm32/no-rm32
    33377     0/imm32/no-r32
    33378     0/imm32/no-imm32
    33379     0/imm32/no-imm8
    33380     0/imm32/no-disp32
    33381     0/imm32/no-xm32
    33382     0/imm32/no-x32
    33383     0x11/imm32/alloc-id:fake
    33384     _Primitive-loop-if-float>=/imm32/next
    33385 _Primitive-loop-if-float>=:  # (payload primitive)
    33386     0x11/imm32/alloc-id:fake:payload
    33387     0x11/imm32/alloc-id:fake
    33388     _string-loop-if-float>=/imm32/name
    33389     0/imm32/no-inouts
    33390     0/imm32/no-inouts
    33391     0/imm32/no-outputs
    33392     0/imm32/no-outputs
    33393     0x11/imm32/alloc-id:fake
    33394     _string_0f_83_jump_loop/imm32/subx-name
    33395     0/imm32/no-rm32
    33396     0/imm32/no-r32
    33397     0/imm32/no-imm32
    33398     0/imm32/no-imm8
    33399     0/imm32/no-disp32
    33400     0/imm32/no-xm32
    33401     0/imm32/no-x32
    33402     0x11/imm32/alloc-id:fake
    33403     _Primitive-loop-if-float<=/imm32/next
    33404 _Primitive-loop-if-float<=:  # (payload primitive)
    33405     0x11/imm32/alloc-id:fake:payload
    33406     0x11/imm32/alloc-id:fake
    33407     _string-loop-if-float<=/imm32/name
    33408     0/imm32/no-inouts
    33409     0/imm32/no-inouts
    33410     0/imm32/no-outputs
    33411     0/imm32/no-outputs
    33412     0x11/imm32/alloc-id:fake
    33413     _string_0f_86_jump_loop/imm32/subx-name
    33414     0/imm32/no-rm32
    33415     0/imm32/no-r32
    33416     0/imm32/no-imm32
    33417     0/imm32/no-imm8
    33418     0/imm32/no-disp32
    33419     0/imm32/no-xm32
    33420     0/imm32/no-x32
    33421     0x11/imm32/alloc-id:fake
    33422     _Primitive-loop-if-float>/imm32/next
    33423 _Primitive-loop-if-float>:  # (payload primitive)
    33424     0x11/imm32/alloc-id:fake:payload
    33425     0x11/imm32/alloc-id:fake
    33426     _string-loop-if-float>/imm32/name
    33427     0/imm32/no-inouts
    33428     0/imm32/no-inouts
    33429     0/imm32/no-outputs
    33430     0/imm32/no-outputs
    33431     0x11/imm32/alloc-id:fake
    33432     _string_0f_87_jump_loop/imm32/subx-name
    33433     0/imm32/no-rm32
    33434     0/imm32/no-r32
    33435     0/imm32/no-imm32
    33436     0/imm32/no-imm8
    33437     0/imm32/no-disp32
    33438     0/imm32/no-xm32
    33439     0/imm32/no-x32
    33440     0x11/imm32/alloc-id:fake
    33441     _Primitive-break-if-float<-named/imm32/next
    33442 _Primitive-break-if-float<-named:  # (payload primitive)
    33443     0x11/imm32/alloc-id:fake:payload
    33444     0x11/imm32/alloc-id:fake
    33445     _string-break-if-float</imm32/name
    33446     0x11/imm32/alloc-id:fake
    33447     Single-lit-var/imm32/inouts
    33448     0/imm32/no-outputs
    33449     0/imm32/no-outputs
    33450     0x11/imm32/alloc-id:fake
    33451     _string_0f_82_jump_label/imm32/subx-name
    33452     0/imm32/no-rm32
    33453     0/imm32/no-r32
    33454     0/imm32/no-imm32
    33455     0/imm32/no-imm8
    33456     1/imm32/disp32-is-first-inout
    33457     0/imm32/no-xm32
    33458     0/imm32/no-x32
    33459     0x11/imm32/alloc-id:fake
    33460     _Primitive-break-if-float>=-named/imm32/next
    33461 _Primitive-break-if-float>=-named:  # (payload primitive)
    33462     0x11/imm32/alloc-id:fake:payload
    33463     0x11/imm32/alloc-id:fake
    33464     _string-break-if-float>=/imm32/name
    33465     0x11/imm32/alloc-id:fake
    33466     Single-lit-var/imm32/inouts
    33467     0/imm32/no-outputs
    33468     0/imm32/no-outputs
    33469     0x11/imm32/alloc-id:fake
    33470     _string_0f_83_jump_label/imm32/subx-name
    33471     0/imm32/no-rm32
    33472     0/imm32/no-r32
    33473     0/imm32/no-imm32
    33474     0/imm32/no-imm8
    33475     1/imm32/disp32-is-first-inout
    33476     0/imm32/no-xm32
    33477     0/imm32/no-x32
    33478     0x11/imm32/alloc-id:fake
    33479     _Primitive-break-if-float<=-named/imm32/next
    33480 _Primitive-break-if-float<=-named:  # (payload primitive)
    33481     0x11/imm32/alloc-id:fake:payload
    33482     0x11/imm32/alloc-id:fake
    33483     _string-break-if-float<=/imm32/name
    33484     0x11/imm32/alloc-id:fake
    33485     Single-lit-var/imm32/inouts
    33486     0/imm32/no-outputs
    33487     0/imm32/no-outputs
    33488     0x11/imm32/alloc-id:fake
    33489     _string_0f_86_jump_label/imm32/subx-name
    33490     0/imm32/no-rm32
    33491     0/imm32/no-r32
    33492     0/imm32/no-imm32
    33493     0/imm32/no-imm8
    33494     1/imm32/disp32-is-first-inout
    33495     0/imm32/no-xm32
    33496     0/imm32/no-x32
    33497     0x11/imm32/alloc-id:fake
    33498     _Primitive-break-if-float>-named/imm32/next
    33499 _Primitive-break-if-float>-named:  # (payload primitive)
    33500     0x11/imm32/alloc-id:fake:payload
    33501     0x11/imm32/alloc-id:fake
    33502     _string-break-if-float>/imm32/name
    33503     0x11/imm32/alloc-id:fake
    33504     Single-lit-var/imm32/inouts
    33505     0/imm32/no-outputs
    33506     0/imm32/no-outputs
    33507     0x11/imm32/alloc-id:fake
    33508     _string_0f_87_jump_label/imm32/subx-name
    33509     0/imm32/no-rm32
    33510     0/imm32/no-r32
    33511     0/imm32/no-imm32
    33512     0/imm32/no-imm8
    33513     1/imm32/disp32-is-first-inout
    33514     0/imm32/no-xm32
    33515     0/imm32/no-x32
    33516     0x11/imm32/alloc-id:fake
    33517     _Primitive-loop-if-float<-named/imm32/next
    33518 _Primitive-loop-if-float<-named:  # (payload primitive)
    33519     0x11/imm32/alloc-id:fake:payload
    33520     0x11/imm32/alloc-id:fake
    33521     _string-loop-if-float</imm32/name
    33522     0x11/imm32/alloc-id:fake
    33523     Single-lit-var/imm32/inouts
    33524     0/imm32/no-outputs
    33525     0/imm32/no-outputs
    33526     0x11/imm32/alloc-id:fake
    33527     _string_0f_82_jump_label/imm32/subx-name
    33528     0/imm32/no-rm32
    33529     0/imm32/no-r32
    33530     0/imm32/no-imm32
    33531     0/imm32/no-imm8
    33532     1/imm32/disp32-is-first-inout
    33533     0/imm32/no-xm32
    33534     0/imm32/no-x32
    33535     0x11/imm32/alloc-id:fake
    33536     _Primitive-loop-if-float>=-named/imm32/next
    33537 _Primitive-loop-if-float>=-named:  # (payload primitive)
    33538     0x11/imm32/alloc-id:fake:payload
    33539     0x11/imm32/alloc-id:fake
    33540     _string-loop-if-float>=/imm32/name
    33541     0x11/imm32/alloc-id:fake
    33542     Single-lit-var/imm32/inouts
    33543     0/imm32/no-outputs
    33544     0/imm32/no-outputs
    33545     0x11/imm32/alloc-id:fake
    33546     _string_0f_83_jump_label/imm32/subx-name
    33547     0/imm32/no-rm32
    33548     0/imm32/no-r32
    33549     0/imm32/no-imm32
    33550     0/imm32/no-imm8
    33551     1/imm32/disp32-is-first-inout
    33552     0/imm32/no-xm32
    33553     0/imm32/no-x32
    33554     0x11/imm32/alloc-id:fake
    33555     _Primitive-loop-if-float<=-named/imm32/next
    33556 _Primitive-loop-if-float<=-named:  # (payload primitive)
    33557     0x11/imm32/alloc-id:fake:payload
    33558     0x11/imm32/alloc-id:fake
    33559     _string-loop-if-float<=/imm32/name
    33560     0x11/imm32/alloc-id:fake
    33561     Single-lit-var/imm32/inouts
    33562     0/imm32/no-outputs
    33563     0/imm32/no-outputs
    33564     0x11/imm32/alloc-id:fake
    33565     _string_0f_86_jump_label/imm32/subx-name
    33566     0/imm32/no-rm32
    33567     0/imm32/no-r32
    33568     0/imm32/no-imm32
    33569     0/imm32/no-imm8
    33570     1/imm32/disp32-is-first-inout
    33571     0/imm32/no-xm32
    33572     0/imm32/no-x32
    33573     0x11/imm32/alloc-id:fake
    33574     _Primitive-loop-if-float>-named/imm32/next
    33575 _Primitive-loop-if-float>-named:  # (payload primitive)
    33576     0x11/imm32/alloc-id:fake:payload
    33577     0x11/imm32/alloc-id:fake
    33578     _string-loop-if-float>/imm32/name
    33579     0x11/imm32/alloc-id:fake
    33580     Single-lit-var/imm32/inouts
    33581     0/imm32/no-outputs
    33582     0/imm32/no-outputs
    33583     0x11/imm32/alloc-id:fake
    33584     _string_0f_87_jump_label/imm32/subx-name
    33585     0/imm32/no-rm32
    33586     0/imm32/no-r32
    33587     0/imm32/no-imm32
    33588     0/imm32/no-imm8
    33589     1/imm32/disp32-is-first-inout
    33590     0/imm32/no-xm32
    33591     0/imm32/no-x32
    33592     0/imm32/next
    33593     0/imm32/next
    33594
    33595 # string literals for Mu instructions
    33596 _string-add:  # (payload array byte)
    33597     0x11/imm32/alloc-id:fake:payload
    33598     # "add"
    33599     0x3/imm32/size
    33600     0x61/a 0x64/d 0x64/d
    33601 _string-address:  # (payload array byte)
    33602     0x11/imm32/alloc-id:fake:payload
    33603     # "address"
    33604     0x7/imm32/size
    33605     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
    33606 _string-add-to:  # (payload array byte)
    33607     0x11/imm32/alloc-id:fake:payload
    33608     # "add-to"
    33609     0x6/imm32/size
    33610     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    33611 _string-and:  # (payload array byte)
    33612     0x11/imm32/alloc-id:fake:payload
    33613     # "and"
    33614     0x3/imm32/size
    33615     0x61/a 0x6e/n 0x64/d
    33616 _string-and-with:  # (payload array byte)
    33617     0x11/imm32/alloc-id:fake:payload
    33618     # "and-with"
    33619     0x8/imm32/size
    33620     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    33621 _string-break:  # (payload array byte)
    33622     0x11/imm32/alloc-id:fake:payload
    33623     # "break"
    33624     0x5/imm32/size
    33625     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
    33626 _string-break-if-<:  # (payload array byte)
    33627     0x11/imm32/alloc-id:fake:payload
    33628     # "break-if-<"
    33629     0xa/imm32/size
    33630     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    33631 _string-break-if-<=:  # (payload array byte)
    33632     0x11/imm32/alloc-id:fake:payload
    33633     # "break-if-<="
    33634     0xb/imm32/size
    33635     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    33636 _string-break-if-=:  # (payload array byte)
    33637     0x11/imm32/alloc-id:fake:payload
    33638     # "break-if-="
    33639     0xa/imm32/size
    33640     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    33641 _string-break-if->:  # (payload array byte)
    33642     0x11/imm32/alloc-id:fake:payload
    33643     # "break-if->"
    33644     0xa/imm32/size
    33645     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    33646 _string-break-if->=:  # (payload array byte)
    33647     0x11/imm32/alloc-id:fake:payload
    33648     # "break-if->="
    33649     0xb/imm32/size
    33650     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    33651 _string-break-if-!=:  # (payload array byte)
    33652     0x11/imm32/alloc-id:fake:payload
    33653     # "break-if-!="
    33654     0xb/imm32/size
    33655     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    33656 _string-break-if-addr<:  # (payload array byte)
    33657     0x11/imm32/alloc-id:fake:payload
    33658     # "break-if-addr<"
    33659     0xe/imm32/size
    33660     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/<
    33661 _string-break-if-addr<=:  # (payload array byte)
    33662     0x11/imm32/alloc-id:fake:payload
    33663     # "break-if-addr<="
    33664     0xf/imm32/size
    33665     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/=
    33666 _string-break-if-addr>:  # (payload array byte)
    33667     0x11/imm32/alloc-id:fake:payload
    33668     # "break-if-addr>"
    33669     0xe/imm32/size
    33670     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/>
    33671 _string-break-if-addr>=:  # (payload array byte)
    33672     0x11/imm32/alloc-id:fake:payload
    33673     # "break-if-addr>="
    33674     0xf/imm32/size
    33675     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/=
    33676 _string-break-if-float<:  # (payload array byte)
    33677     0x11/imm32/alloc-id:fake:payload
    33678     # "break-if-float<"
    33679     0xf/imm32/size
    33680     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/<
    33681 _string-break-if-float<=:  # (payload array byte)
    33682     0x11/imm32/alloc-id:fake:payload
    33683     # "break-if-float<="
    33684     0x10/imm32/size
    33685     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/=
    33686 _string-break-if-float>:  # (payload array byte)
    33687     0x11/imm32/alloc-id:fake:payload
    33688     # "break-if-float>"
    33689     0xf/imm32/size
    33690     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/>
    33691 _string-break-if-float>=:  # (payload array byte)
    33692     0x11/imm32/alloc-id:fake:payload
    33693     # "break-if-float>="
    33694     0x10/imm32/size
    33695     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/=
    33696 _string-compare:  # (payload array byte)
    33697     0x11/imm32/alloc-id:fake:payload
    33698     # "compare"
    33699     0x7/imm32/size
    33700     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
    33701 _string-copy:  # (payload array byte)
    33702     0x11/imm32/alloc-id:fake:payload
    33703     # "copy"
    33704     0x4/imm32/size
    33705     0x63/c 0x6f/o 0x70/p 0x79/y
    33706 _string-copy-to:  # (payload array byte)
    33707     0x11/imm32/alloc-id:fake:payload
    33708     # "copy-to"
    33709     0x7/imm32/size
    33710     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
    33711 _string-copy-byte:
    33712     0x11/imm32/alloc-id:fake:payload
    33713     # "copy-byte"
    33714     0x9/imm32/size
    33715     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
    33716 _string-copy-byte-to:
    33717     0x11/imm32/alloc-id:fake:payload
    33718     # "copy-byte-to"
    33719     0xc/imm32/size
    33720     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
    33721 _string-decrement:  # (payload array byte)
    33722     0x11/imm32/alloc-id:fake:payload
    33723     # "decrement"
    33724     0x9/imm32/size
    33725     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    33726 _string-increment:  # (payload array byte)
    33727     0x11/imm32/alloc-id:fake:payload
    33728     # "increment"
    33729     0x9/imm32/size
    33730     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    33731 _string-loop:  # (payload array byte)
    33732     0x11/imm32/alloc-id:fake:payload
    33733     # "loop"
    33734     0x4/imm32/size
    33735     0x6c/l 0x6f/o 0x6f/o 0x70/p
    33736 _string-loop-if-<:  # (payload array byte)
    33737     0x11/imm32/alloc-id:fake:payload
    33738     # "loop-if-<"
    33739     0x9/imm32/size
    33740     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    33741 _string-loop-if-<=:  # (payload array byte)
    33742     0x11/imm32/alloc-id:fake:payload
    33743     # "loop-if-<="
    33744     0xa/imm32/size
    33745     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    33746 _string-loop-if-=:  # (payload array byte)
    33747     0x11/imm32/alloc-id:fake:payload
    33748     # "loop-if-="
    33749     0x9/imm32/size
    33750     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    33751 _string-loop-if->:  # (payload array byte)
    33752     0x11/imm32/alloc-id:fake:payload
    33753     # "loop-if->"
    33754     0x9/imm32/size
    33755     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    33756 _string-loop-if->=:  # (payload array byte)
    33757     0x11/imm32/alloc-id:fake:payload
    33758     # "loop-if->="
    33759     0xa/imm32/size
    33760     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    33761 _string-loop-if-!=:  # (payload array byte)
    33762     0x11/imm32/alloc-id:fake:payload
    33763     # "loop-if-!="
    33764     0xa/imm32/size
    33765     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    33766 _string-loop-if-addr<:  # (payload array byte)
    33767     0x11/imm32/alloc-id:fake:payload
    33768     # "loop-if-addr<"
    33769     0xd/imm32/size
    33770     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/<
    33771 _string-loop-if-addr<=:  # (payload array byte)
    33772     0x11/imm32/alloc-id:fake:payload
    33773     # "loop-if-addr<="
    33774     0xe/imm32/size
    33775     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/=
    33776 _string-loop-if-addr>:  # (payload array byte)
    33777     0x11/imm32/alloc-id:fake:payload
    33778     # "loop-if-addr>"
    33779     0xd/imm32/size
    33780     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/>
    33781 _string-loop-if-addr>=:  # (payload array byte)
    33782     0x11/imm32/alloc-id:fake:payload
    33783     # "loop-if-addr>="
    33784     0xe/imm32/size
    33785     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/=
    33786 _string-loop-if-float<:  # (payload array byte)
    33787     0x11/imm32/alloc-id:fake:payload
    33788     # "loop-if-float<"
    33789     0xe/imm32/size
    33790     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/<
    33791 _string-loop-if-float<=:  # (payload array byte)
    33792     0x11/imm32/alloc-id:fake:payload
    33793     # "loop-if-float<="
    33794     0xf/imm32/size
    33795     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/=
    33796 _string-loop-if-float>:  # (payload array byte)
    33797     0x11/imm32/alloc-id:fake:payload
    33798     # "loop-if-float>"
    33799     0xe/imm32/size
    33800     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/>
    33801 _string-loop-if-float>=:  # (payload array byte)
    33802     0x11/imm32/alloc-id:fake:payload
    33803     # "loop-if-float>="
    33804     0xf/imm32/size
    33805     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/=
    33806 _string-multiply:  # (payload array byte)
    33807     0x11/imm32/alloc-id:fake:payload
    33808     # "multiply"
    33809     0x8/imm32/size
    33810     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
    33811 _string-convert:  # (payload array byte)
    33812     0x11/imm32/alloc-id:fake:payload
    33813     # "convert"
    33814     0x7/imm32/size
    33815     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
    33816 _string-truncate:  # (payload array byte)
    33817     0x11/imm32/alloc-id:fake:payload
    33818     # "truncate"
    33819     0x8/imm32/size
    33820     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
    33821 _string-reinterpret:  # (payload array byte)
    33822     0x11/imm32/alloc-id:fake:payload
    33823     # "reinterpret"
    33824     0xb/imm32/size
    33825     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
    33826 _string-divide:
    33827     0x11/imm32/alloc-id:fake:payload
    33828     # "divide"
    33829     0x6/imm32/size
    33830     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
    33831 _string-max:
    33832     0x11/imm32/alloc-id:fake:payload
    33833     # "max"
    33834     0x3/imm32/size
    33835     0x6d/m 0x61/a 0x78/x
    33836 _string-min:
    33837     0x11/imm32/alloc-id:fake:payload
    33838     # "min"
    33839     0x3/imm32/size
    33840     0x6d/m 0x69/i 0x6e/n
    33841 _string-reciprocal:
    33842     0x11/imm32/alloc-id:fake:payload
    33843     # "reciprocal"
    33844     0xa/imm32/size
    33845     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
    33846 _string-square-root:
    33847     0x11/imm32/alloc-id:fake:payload
    33848     # "square-root"
    33849     0xb/imm32/size
    33850     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
    33851 _string-inverse-square-root:
    33852     0x11/imm32/alloc-id:fake:payload
    33853     # "inverse-square-root"
    33854     0x13/imm32/size
    33855     0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
    33856 _string-negate:  # (payload array byte)
    33857     0x11/imm32/alloc-id:fake:payload
    33858     # "negate"
    33859     0x6/imm32/size
    33860     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
    33861 _string-or:  # (payload array byte)
    33862     0x11/imm32/alloc-id:fake:payload
    33863     # "or"
    33864     0x2/imm32/size
    33865     0x6f/o 0x72/r
    33866 _string-or-with:  # (payload array byte)
    33867     0x11/imm32/alloc-id:fake:payload
    33868     # "or-with"
    33869     0x7/imm32/size
    33870     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    33871 _string-subtract:  # (payload array byte)
    33872     0x11/imm32/alloc-id:fake:payload
    33873     # "subtract"
    33874     0x8/imm32/size
    33875     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    33876 _string-subtract-from:  # (payload array byte)
    33877     0x11/imm32/alloc-id:fake:payload
    33878     # "subtract-from"
    33879     0xd/imm32/size
    33880     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
    33881 _string-xor:  # (payload array byte)
    33882     0x11/imm32/alloc-id:fake:payload
    33883     # "xor"
    33884     0x3/imm32/size
    33885     0x78/x 0x6f/o 0x72/r
    33886 _string-xor-with:  # (payload array byte)
    33887     0x11/imm32/alloc-id:fake:payload
    33888     # "xor-with"
    33889     0x8/imm32/size
    33890     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    33891 _string-shift-left:  # (payload array byte)
    33892     0x11/imm32/alloc-id:fake:payload
    33893     # "shift-left"
    33894     0xa/imm32/size
    33895     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
    33896 _string-shift-right:  # (payload array byte)
    33897     0x11/imm32/alloc-id:fake:payload
    33898     # "shift-right"
    33899     0xb/imm32/size
    33900     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
    33901 _string-shift-right-signed:  # (payload array byte)
    33902     0x11/imm32/alloc-id:fake:payload
    33903     # "shift-right-signed"
    33904     0x12/imm32/size
    33905     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
    33906
    33907 # string literals for SubX instructions
    33908 _string_01_add_to:  # (payload array byte)
    33909     0x11/imm32/alloc-id:fake:payload
    33910     # "01/add-to"
    33911     0x9/imm32/size
    33912     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    33913 _string_03_add:  # (payload array byte)
    33914     0x11/imm32/alloc-id:fake:payload
    33915     # "03/add"
    33916     0x6/imm32/size
    33917     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
    33918 _string_05_add_to_eax:  # (payload array byte)
    33919     0x11/imm32/alloc-id:fake:payload
    33920     # "05/add-to-eax"
    33921     0xd/imm32/size
    33922     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
    33923 _string_09_or_with:  # (payload array byte)
    33924     0x11/imm32/alloc-id:fake:payload
    33925     # "09/or-with"
    33926     0xa/imm32/size
    33927     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    33928 _string_0b_or:  # (payload array byte)
    33929     0x11/imm32/alloc-id:fake:payload
    33930     # "0b/or"
    33931     0x5/imm32/size
    33932     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
    33933 _string_0d_or_with_eax:  # (payload array byte)
    33934     0x11/imm32/alloc-id:fake:payload
    33935     # "0d/or-with-eax"
    33936     0xe/imm32/size
    33937     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
    33938 _string_0f_82_jump_label:  # (payload array byte)
    33939     0x11/imm32/alloc-id:fake:payload
    33940     # "0f 82/jump-if-addr<"
    33941     0x13/imm32/size
    33942     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/<
    33943 _string_0f_82_jump_break:  # (payload array byte)
    33944     0x11/imm32/alloc-id:fake:payload
    33945     # "0f 82/jump-if-addr< break/disp32"
    33946     0x20/imm32/size
    33947     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
    33948 _string_0f_82_jump_loop:  # (payload array byte)
    33949     0x11/imm32/alloc-id:fake:payload
    33950     # "0f 82/jump-if-addr< loop/disp32"
    33951     0x1f/imm32/size
    33952     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
    33953 _string_0f_83_jump_label:  # (payload array byte)
    33954     0x11/imm32/alloc-id:fake:payload
    33955     # "0f 83/jump-if-addr>="
    33956     0x14/imm32/size
    33957     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/=
    33958 _string_0f_83_jump_break:  # (payload array byte)
    33959     0x11/imm32/alloc-id:fake:payload
    33960     # "0f 83/jump-if-addr>= break/disp32"
    33961     0x21/imm32/size
    33962     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
    33963 _string_0f_83_jump_loop:  # (payload array byte)
    33964     0x11/imm32/alloc-id:fake:payload
    33965     # "0f 83/jump-if-addr>= loop/disp32"
    33966     0x20/imm32/size
    33967     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
    33968 _string_0f_84_jump_label:  # (payload array byte)
    33969     0x11/imm32/alloc-id:fake:payload
    33970     # "0f 84/jump-if-="
    33971     0xf/imm32/size
    33972     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/=
    33973 _string_0f_84_jump_break:  # (payload array byte)
    33974     0x11/imm32/alloc-id:fake:payload
    33975     # "0f 84/jump-if-= break/disp32"
    33976     0x1c/imm32/size
    33977     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
    33978 _string_0f_84_jump_loop:  # (payload array byte)
    33979     0x11/imm32/alloc-id:fake:payload
    33980     # "0f 84/jump-if-= loop/disp32"
    33981     0x1b/imm32/size
    33982     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
    33983 _string_0f_85_jump_label:  # (payload array byte)
    33984     0x11/imm32/alloc-id:fake:payload
    33985     # "0f 85/jump-if-!="
    33986     0x10/imm32/size
    33987     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/=
    33988 _string_0f_85_jump_break:  # (payload array byte)
    33989     0x11/imm32/alloc-id:fake:payload
    33990     # "0f 85/jump-if-!= break/disp32"
    33991     0x1d/imm32/size
    33992     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
    33993 _string_0f_85_jump_loop:  # (payload array byte)
    33994     0x11/imm32/alloc-id:fake:payload
    33995     # "0f 85/jump-if-!= loop/disp32"
    33996     0x1c/imm32/size
    33997     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
    33998 _string_0f_86_jump_label:  # (payload array byte)
    33999     0x11/imm32/alloc-id:fake:payload
    34000     # "0f 86/jump-if-addr<="
    34001     0x14/imm32/size
    34002     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/=
    34003 _string_0f_86_jump_break:  # (payload array byte)
    34004     0x11/imm32/alloc-id:fake:payload
    34005     # "0f 86/jump-if-addr<= break/disp32"
    34006     0x21/imm32/size
    34007     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
    34008 _string_0f_86_jump_loop:  # (payload array byte)
    34009     0x11/imm32/alloc-id:fake:payload
    34010     # "0f 86/jump-if-addr<= loop/disp32"
    34011     0x20/imm32/size
    34012     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
    34013 _string_0f_87_jump_label:  # (payload array byte)
    34014     0x11/imm32/alloc-id:fake:payload
    34015     # "0f 87/jump-if-addr>"
    34016     0x13/imm32/size
    34017     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/>
    34018 _string_0f_87_jump_break:  # (payload array byte)
    34019     0x11/imm32/alloc-id:fake:payload
    34020     # "0f 87/jump-if-addr> break/disp32"
    34021     0x20/imm32/size
    34022     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
    34023 _string_0f_87_jump_loop:  # (payload array byte)
    34024     0x11/imm32/alloc-id:fake:payload
    34025     # "0f 87/jump-if-addr> loop/disp32"
    34026     0x1f/imm32/size
    34027     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
    34028 _string_0f_8c_jump_label:  # (payload array byte)
    34029     0x11/imm32/alloc-id:fake:payload
    34030     # "0f 8c/jump-if-<"
    34031     0xf/imm32/size
    34032     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/<
    34033 _string_0f_8c_jump_break:  # (payload array byte)
    34034     0x11/imm32/alloc-id:fake:payload
    34035     # "0f 8c/jump-if-< break/disp32"
    34036     0x1c/imm32/size
    34037     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
    34038 _string_0f_8c_jump_loop:  # (payload array byte)
    34039     0x11/imm32/alloc-id:fake:payload
    34040     # "0f 8c/jump-if-< loop/disp32"
    34041     0x1b/imm32/size
    34042     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
    34043 _string_0f_8d_jump_label:  # (payload array byte)
    34044     0x11/imm32/alloc-id:fake:payload
    34045     # "0f 8d/jump-if->="
    34046     0x10/imm32/size
    34047     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/=
    34048 _string_0f_8d_jump_break:  # (payload array byte)
    34049     0x11/imm32/alloc-id:fake:payload
    34050     # "0f 8d/jump-if->= break/disp32"
    34051     0x1d/imm32/size
    34052     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
    34053 _string_0f_8d_jump_loop:  # (payload array byte)
    34054     0x11/imm32/alloc-id:fake:payload
    34055     # "0f 8d/jump-if->= loop/disp32"
    34056     0x1c/imm32/size
    34057     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
    34058 _string_0f_8e_jump_label:  # (payload array byte)
    34059     0x11/imm32/alloc-id:fake:payload
    34060     # "0f 8e/jump-if-<="
    34061     0x10/imm32/size
    34062     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/=
    34063 _string_0f_8e_jump_break:  # (payload array byte)
    34064     0x11/imm32/alloc-id:fake:payload
    34065     # "0f 8e/jump-if-<= break/disp32"
    34066     0x1d/imm32/size
    34067     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
    34068 _string_0f_8e_jump_loop:  # (payload array byte)
    34069     0x11/imm32/alloc-id:fake:payload
    34070     # "0f 8e/jump-if-<= loop/disp32"
    34071     0x1c/imm32/size
    34072     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
    34073 _string_0f_8f_jump_label:  # (payload array byte)
    34074     0x11/imm32/alloc-id:fake:payload
    34075     # "0f 8f/jump-if->"
    34076     0xf/imm32/size
    34077     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/>
    34078 _string_0f_8f_jump_break:  # (payload array byte)
    34079     0x11/imm32/alloc-id:fake:payload
    34080     # "0f 8f/jump-if-> break/disp32"
    34081     0x1c/imm32/size
    34082     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
    34083 _string_0f_8f_jump_loop:  # (payload array byte)
    34084     0x11/imm32/alloc-id:fake:payload
    34085     # "0f 8f/jump-if-> loop/disp32"
    34086     0x1b/imm32/size
    34087     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
    34088 _string_0f_af_multiply:  # (payload array byte)
    34089     0x11/imm32/alloc-id:fake:payload
    34090     # "0f af/multiply"
    34091     0xe/imm32/size
    34092     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
    34093 _string_f3_0f_2a_convert_to_float:
    34094     0x11/imm32/alloc-id:fake:payload
    34095     # "f3 0f 2a/convert-to-float"
    34096     0x19/imm32/size
    34097     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
    34098 _string_f3_0f_2d_convert_to_int:
    34099     0x11/imm32/alloc-id:fake:payload
    34100     # "f3 0f 2d/convert-to-int"
    34101     0x17/imm32/size
    34102     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
    34103 _string_f3_0f_2c_truncate_to_int:
    34104     0x11/imm32/alloc-id:fake:payload
    34105     # "f3 0f 2c/truncate-to-int"
    34106     0x18/imm32/size
    34107     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
    34108 _string_f3_0f_58_add:
    34109     0x11/imm32/alloc-id:fake:payload
    34110     # "f3 0f 58/add"
    34111     0xc/imm32/size
    34112     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
    34113 _string_f3_0f_5c_subtract:
    34114     0x11/imm32/alloc-id:fake:payload
    34115     # "f3 0f 5c/subtract"
    34116     0x11/imm32/size
    34117     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
    34118 _string_f3_0f_59_multiply:
    34119     0x11/imm32/alloc-id:fake:payload
    34120     # "f3 0f 59/multiply"
    34121     0x11/imm32/size
    34122     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
    34123 _string_f3_0f_5e_divide:
    34124     0x11/imm32/alloc-id:fake:payload
    34125     # "f3 0f 5e/divide"
    34126     0xf/imm32/size
    34127     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
    34128 _string_f3_0f_53_reciprocal:
    34129     0x11/imm32/alloc-id:fake:payload
    34130     # "f3 0f 53/reciprocal"
    34131     0x13/imm32/size
    34132     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
    34133 _string_f3_0f_51_square_root:
    34134     0x11/imm32/alloc-id:fake:payload
    34135     # "f3 0f 51/square-root"
    34136     0x14/imm32/size
    34137     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
    34138 _string_f3_0f_52_inverse_square_root:
    34139     0x11/imm32/alloc-id:fake:payload
    34140     # "f3 0f 52/inverse-square-root"
    34141     0x1c/imm32/size
    34142     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
    34143 _string_f3_0f_5d_min:
    34144     0x11/imm32/alloc-id:fake:payload
    34145     # "f3 0f 5d/min"
    34146     0xc/imm32/size
    34147     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
    34148 _string_f3_0f_5f_max:
    34149     0x11/imm32/alloc-id:fake:payload
    34150     # "f3 0f 5f/max"
    34151     0xc/imm32/size
    34152     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
    34153 _string_f3_0f_10_copy:
    34154     0x11/imm32/alloc-id:fake:payload
    34155     # "f3 0f 10/copy"
    34156     0xd/imm32/size
    34157     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
    34158 _string_f3_0f_11_copy:
    34159     0x11/imm32/alloc-id:fake:payload
    34160     # "f3 0f 11/copy"
    34161     0xd/imm32/size
    34162     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
    34163 _string_0f_2f_compare:
    34164     0x11/imm32/alloc-id:fake:payload
    34165     # "0f 2f/compare"
    34166     0xd/imm32/size
    34167     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
    34168 _string_21_and_with:  # (payload array byte)
    34169     0x11/imm32/alloc-id:fake:payload
    34170     # "21/and-with"
    34171     0xb/imm32/size
    34172     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34173 _string_23_and:  # (payload array byte)
    34174     0x11/imm32/alloc-id:fake:payload
    34175     # "23/and"
    34176     0x6/imm32/size
    34177     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
    34178 _string_25_and_with_eax:  # (payload array byte)
    34179     0x11/imm32/alloc-id:fake:payload
    34180     # "25/and-with-eax"
    34181     0xf/imm32/size
    34182     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
    34183 _string_29_subtract_from:  # (payload array byte)
    34184     0x11/imm32/alloc-id:fake:payload
    34185     # "29/subtract-from"
    34186     0x10/imm32/size
    34187     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
    34188 _string_2b_subtract:  # (payload array byte)
    34189     0x11/imm32/alloc-id:fake:payload
    34190     # "2b/subtract"
    34191     0xb/imm32/size
    34192     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34193 _string_2d_subtract_from_eax:  # (payload array byte)
    34194     0x11/imm32/alloc-id:fake:payload
    34195     # "2d/subtract-from-eax"
    34196     0x14/imm32/size
    34197     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
    34198 _string_31_xor_with:  # (payload array byte)
    34199     0x11/imm32/alloc-id:fake:payload
    34200     # "31/xor-with"
    34201     0xb/imm32/size
    34202     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34203 _string_33_xor:  # (payload array byte)
    34204     0x11/imm32/alloc-id:fake:payload
    34205     # "33/xor"
    34206     0x6/imm32/size
    34207     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
    34208 _string_35_xor_with_eax:  # (payload array byte)
    34209     0x11/imm32/alloc-id:fake:payload
    34210     # "35/xor-with-eax"
    34211     0xf/imm32/size
    34212     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
    34213 _string_39_compare->:  # (payload array byte)
    34214     0x11/imm32/alloc-id:fake:payload
    34215     # "39/compare->"
    34216     0xc/imm32/size
    34217     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
    34218 _string_3b_compare<-:  # (payload array byte)
    34219     0x11/imm32/alloc-id:fake:payload
    34220     # "3b/compare<-"
    34221     0xc/imm32/size
    34222     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
    34223 _string_3d_compare_eax_with:  # (payload array byte)
    34224     0x11/imm32/alloc-id:fake:payload
    34225     # "3d/compare-eax-with"
    34226     0x13/imm32/size
    34227     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
    34228 _string_40_increment_eax:  # (payload array byte)
    34229     0x11/imm32/alloc-id:fake:payload
    34230     # "40/increment-eax"
    34231     0x10/imm32/size
    34232     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
    34233 _string_41_increment_ecx:  # (payload array byte)
    34234     0x11/imm32/alloc-id:fake:payload
    34235     # "41/increment-ecx"
    34236     0x10/imm32/size
    34237     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
    34238 _string_42_increment_edx:  # (payload array byte)
    34239     0x11/imm32/alloc-id:fake:payload
    34240     # "42/increment-edx"
    34241     0x10/imm32/size
    34242     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
    34243 _string_43_increment_ebx:  # (payload array byte)
    34244     0x11/imm32/alloc-id:fake:payload
    34245     # "43/increment-ebx"
    34246     0x10/imm32/size
    34247     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
    34248 _string_46_increment_esi:  # (payload array byte)
    34249     0x11/imm32/alloc-id:fake:payload
    34250     # "46/increment-esi"
    34251     0x10/imm32/size
    34252     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
    34253 _string_47_increment_edi:  # (payload array byte)
    34254     0x11/imm32/alloc-id:fake:payload
    34255     # "47/increment-edi"
    34256     0x10/imm32/size
    34257     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
    34258 _string_48_decrement_eax:  # (payload array byte)
    34259     0x11/imm32/alloc-id:fake:payload
    34260     # "48/decrement-eax"
    34261     0x10/imm32/size
    34262     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
    34263 _string_49_decrement_ecx:  # (payload array byte)
    34264     0x11/imm32/alloc-id:fake:payload
    34265     # "49/decrement-ecx"
    34266     0x10/imm32/size
    34267     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
    34268 _string_4a_decrement_edx:  # (payload array byte)
    34269     0x11/imm32/alloc-id:fake:payload
    34270     # "4a/decrement-edx"
    34271     0x10/imm32/size
    34272     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
    34273 _string_4b_decrement_ebx:  # (payload array byte)
    34274     0x11/imm32/alloc-id:fake:payload
    34275     # "4b/decrement-ebx"
    34276     0x10/imm32/size
    34277     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
    34278 _string_4e_decrement_esi:  # (payload array byte)
    34279     0x11/imm32/alloc-id:fake:payload
    34280     # "4e/decrement-esi"
    34281     0x10/imm32/size
    34282     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
    34283 _string_4f_decrement_edi:  # (payload array byte)
    34284     0x11/imm32/alloc-id:fake:payload
    34285     # "4f/decrement-edi"
    34286     0x10/imm32/size
    34287     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
    34288 _string_81_subop_add:  # (payload array byte)
    34289     0x11/imm32/alloc-id:fake:payload
    34290     # "81 0/subop/add"
    34291     0xe/imm32/size
    34292     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
    34293 _string_81_subop_or:  # (payload array byte)
    34294     0x11/imm32/alloc-id:fake:payload
    34295     # "81 1/subop/or"
    34296     0xd/imm32/size
    34297     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
    34298 _string_81_subop_and:  # (payload array byte)
    34299     0x11/imm32/alloc-id:fake:payload
    34300     # "81 4/subop/and"
    34301     0xe/imm32/size
    34302     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
    34303 _string_81_subop_subtract:  # (payload array byte)
    34304     0x11/imm32/alloc-id:fake:payload
    34305     # "81 5/subop/subtract"
    34306     0x13/imm32/size
    34307     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
    34308 _string_81_subop_xor:  # (payload array byte)
    34309     0x11/imm32/alloc-id:fake:payload
    34310     # "81 6/subop/xor"
    34311     0xe/imm32/size
    34312     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
    34313 _string_81_subop_compare:  # (payload array byte)
    34314     0x11/imm32/alloc-id:fake:payload
    34315     # "81 7/subop/compare"
    34316     0x12/imm32/size
    34317     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
    34318 _string_89_<-:  # (payload array byte)
    34319     0x11/imm32/alloc-id:fake:payload
    34320     # "89/<-"
    34321     0x5/imm32/size
    34322     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
    34323 _string_8b_->:  # (payload array byte)
    34324     0x11/imm32/alloc-id:fake:payload
    34325     # "8b/->"
    34326     0x5/imm32/size
    34327     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
    34328 _string_8a_copy_byte:
    34329     0x11/imm32/alloc-id:fake:payload
    34330     # "8a/byte->"
    34331     0x9/imm32/size
    34332     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
    34333 _string_88_copy_byte:
    34334     0x11/imm32/alloc-id:fake:payload
    34335     # "88/byte<-"
    34336     0x9/imm32/size
    34337     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
    34338 _string_8d_copy_address:  # (payload array byte)
    34339     0x11/imm32/alloc-id:fake:payload
    34340     # "8d/copy-address"
    34341     0xf/imm32/size
    34342     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
    34343 _string_b8_copy_to_eax:  # (payload array byte)
    34344     0x11/imm32/alloc-id:fake:payload
    34345     # "b8/copy-to-eax"
    34346     0xe/imm32/size
    34347     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
    34348 _string_b9_copy_to_ecx:  # (payload array byte)
    34349     0x11/imm32/alloc-id:fake:payload
    34350     # "b9/copy-to-ecx"
    34351     0xe/imm32/size
    34352     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
    34353 _string_ba_copy_to_edx:  # (payload array byte)
    34354     0x11/imm32/alloc-id:fake:payload
    34355     # "ba/copy-to-edx"
    34356     0xe/imm32/size
    34357     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
    34358 _string_bb_copy_to_ebx:  # (payload array byte)
    34359     0x11/imm32/alloc-id:fake:payload
    34360     # "bb/copy-to-ebx"
    34361     0xe/imm32/size
    34362     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
    34363 _string_be_copy_to_esi:  # (payload array byte)
    34364     0x11/imm32/alloc-id:fake:payload
    34365     # "be/copy-to-esi"
    34366     0xe/imm32/size
    34367     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
    34368 _string_bf_copy_to_edi:  # (payload array byte)
    34369     0x11/imm32/alloc-id:fake:payload
    34370     # "bf/copy-to-edi"
    34371     0xe/imm32/size
    34372     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
    34373 _string_c7_subop_copy:  # (payload array byte)
    34374     0x11/imm32/alloc-id:fake:payload
    34375     # "c7 0/subop/copy"
    34376     0xf/imm32/size
    34377     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
    34378 _string_e9_jump_label:  # (payload array byte)
    34379     0x11/imm32/alloc-id:fake:payload
    34380     # "e9/jump"
    34381     0x7/imm32/size
    34382     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
    34383 _string_e9_jump_break:  # (payload array byte)
    34384     0x11/imm32/alloc-id:fake:payload
    34385     # "e9/jump break/disp32"
    34386     0x14/imm32/size
    34387     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
    34388 _string_e9_jump_loop:  # (payload array byte)
    34389     0x11/imm32/alloc-id:fake:payload
    34390     # "e9/jump loop/disp32"
    34391     0x13/imm32/size
    34392     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
    34393 _string_f7_subop_negate:
    34394     0x11/imm32/alloc-id:fake:payload
    34395     # "f7 3/subop/negate"
    34396     0x11/imm32/size
    34397     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
    34398 _string_ff_subop_increment:  # (payload array byte)
    34399     0x11/imm32/alloc-id:fake:payload
    34400     # "ff 0/subop/increment"
    34401     0x14/imm32/size
    34402     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
    34403 _string_ff_subop_decrement:  # (payload array byte)
    34404     0x11/imm32/alloc-id:fake:payload
    34405     # "ff 1/subop/decrement"
    34406     0x14/imm32/size
    34407     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
    34408 _string_c1_subop_shift_left:  # (payload array byte)
    34409     0x11/imm32/alloc-id:fake:payload
    34410     # "c1/shift 4/subop/left"
    34411     0x15/imm32/size
    34412     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
    34413 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
    34414     0x11/imm32/alloc-id:fake:payload
    34415     # "c1/shift 5/subop/right-padding-zeroes"
    34416     0x25/imm32/size
    34417     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
    34418 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
    34419     0x11/imm32/alloc-id:fake:payload
    34420     # "c1/shift 7/subop/right-preserving-sign"
    34421     0x26/imm32/size
    34422     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
    34423
    34424 Single-int-var-in-mem:  # (payload list var)
    34425     0x11/imm32/alloc-id:fake:payload
    34426     0x11/imm32/alloc-id:fake
    34427     Int-var-in-mem/imm32
    34428     0/imm32/next
    34429     0/imm32/next
    34430
    34431 Int-var-in-mem:  # (payload var)
    34432     0x11/imm32/alloc-id:fake:payload
    34433     0/imm32/name
    34434     0/imm32/name
    34435     0x11/imm32/alloc-id:fake
    34436     Type-int/imm32
    34437     1/imm32/some-block-depth
    34438     1/imm32/some-stack-offset
    34439     0/imm32/no-register
    34440     0/imm32/no-register
    34441
    34442 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34443 Single-byte-var-in-mem:  # (payload list var)
    34444     0x11/imm32/alloc-id:fake:payload
    34445     0x11/imm32/alloc-id:fake
    34446     Byte-var-in-mem/imm32
    34447     0/imm32/next
    34448     0/imm32/next
    34449
    34450 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34451 Byte-var-in-mem:  # (payload var)
    34452     0x11/imm32/alloc-id:fake:payload
    34453     0/imm32/name
    34454     0/imm32/name
    34455     0x11/imm32/alloc-id:fake
    34456     Type-byte/imm32
    34457     1/imm32/some-block-depth
    34458     1/imm32/some-stack-offset
    34459     0/imm32/no-register
    34460     0/imm32/no-register
    34461
    34462 Two-args-int-stack-int-reg:  # (payload list var)
    34463     0x11/imm32/alloc-id:fake:payload
    34464     0x11/imm32/alloc-id:fake
    34465     Int-var-in-mem/imm32
    34466     0x11/imm32/alloc-id:fake
    34467     Single-int-var-in-some-register/imm32/next
    34468
    34469 Two-int-args-in-regs:  # (payload list var)
    34470     0x11/imm32/alloc-id:fake:payload
    34471     0x11/imm32/alloc-id:fake
    34472     Int-var-in-some-register/imm32
    34473     0x11/imm32/alloc-id:fake
    34474     Single-int-var-in-some-register/imm32/next
    34475
    34476 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34477 Two-args-byte-stack-byte-reg:  # (payload list var)
    34478     0x11/imm32/alloc-id:fake:payload
    34479     0x11/imm32/alloc-id:fake
    34480     Byte-var-in-mem/imm32
    34481     0x11/imm32/alloc-id:fake
    34482     Single-byte-var-in-some-register/imm32/next
    34483
    34484 Two-args-int-reg-int-stack:  # (payload list var)
    34485     0x11/imm32/alloc-id:fake:payload
    34486     0x11/imm32/alloc-id:fake
    34487     Int-var-in-some-register/imm32
    34488     0x11/imm32/alloc-id:fake
    34489     Single-int-var-in-mem/imm32/next
    34490
    34491 Two-args-int-eax-int-literal:  # (payload list var)
    34492     0x11/imm32/alloc-id:fake:payload
    34493     0x11/imm32/alloc-id:fake
    34494     Int-var-in-eax/imm32
    34495     0x11/imm32/alloc-id:fake
    34496     Single-lit-var/imm32/next
    34497
    34498 Int-var-and-literal:  # (payload list var)
    34499     0x11/imm32/alloc-id:fake:payload
    34500     0x11/imm32/alloc-id:fake
    34501     Int-var-in-mem/imm32
    34502     0x11/imm32/alloc-id:fake
    34503     Single-lit-var/imm32/next
    34504
    34505 Int-var-in-register-and-literal:  # (payload list var)
    34506     0x11/imm32/alloc-id:fake:payload
    34507     0x11/imm32/alloc-id:fake
    34508     Int-var-in-some-register/imm32
    34509     0x11/imm32/alloc-id:fake
    34510     Single-lit-var/imm32/next
    34511
    34512 Two-float-args-in-regs:  # (payload list var)
    34513     0x11/imm32/alloc-id:fake:payload
    34514     0x11/imm32/alloc-id:fake
    34515     Float-var-in-some-register/imm32
    34516     0x11/imm32/alloc-id:fake
    34517     Single-float-var-in-some-register/imm32/next
    34518
    34519 Two-args-float-reg-float-stack:  # (payload list var)
    34520     0x11/imm32/alloc-id:fake:payload
    34521     0x11/imm32/alloc-id:fake
    34522     Float-var-in-some-register/imm32
    34523     0x11/imm32/alloc-id:fake
    34524     Single-float-var-in-mem/imm32/next
    34525
    34526 Two-args-float-stack-float-reg:  # (payload list var)
    34527     0x11/imm32/alloc-id:fake:payload
    34528     0x11/imm32/alloc-id:fake
    34529     Float-var-in-mem/imm32
    34530     0x11/imm32/alloc-id:fake
    34531     Single-float-var-in-some-register/imm32/next
    34532
    34533 Single-int-var-in-some-register:  # (payload list var)
    34534     0x11/imm32/alloc-id:fake:payload
    34535     0x11/imm32/alloc-id:fake
    34536     Int-var-in-some-register/imm32
    34537     0/imm32/next
    34538     0/imm32/next
    34539
    34540 Single-addr-var-in-some-register:  # (payload list var)
    34541     0x11/imm32/alloc-id:fake:payload
    34542     0x11/imm32/alloc-id:fake
    34543     Addr-var-in-some-register/imm32
    34544     0/imm32/next
    34545     0/imm32/next
    34546
    34547 Single-byte-var-in-some-register:  # (payload list var)
    34548     0x11/imm32/alloc-id:fake:payload
    34549     0x11/imm32/alloc-id:fake
    34550     Byte-var-in-some-register/imm32
    34551     0/imm32/next
    34552     0/imm32/next
    34553
    34554 Int-var-in-some-register:  # (payload var)
    34555     0x11/imm32/alloc-id:fake:payload
    34556     0/imm32/name
    34557     0/imm32/name
    34558     0x11/imm32/alloc-id:fake
    34559     Type-int/imm32
    34560     1/imm32/some-block-depth
    34561     0/imm32/no-stack-offset
    34562     0x11/imm32/alloc-id:fake
    34563     Any-register/imm32
    34564
    34565 Any-register:  # (payload array byte)
    34566     0x11/imm32/alloc-id:fake:payload
    34567     1/imm32/size
    34568     # data
    34569     2a/asterisk
    34570
    34571 Addr-var-in-some-register:  # (payload var)
    34572     0x11/imm32/alloc-id:fake:payload
    34573     0/imm32/name
    34574     0/imm32/name
    34575     0x11/imm32/alloc-id:fake
    34576     Type-addr/imm32
    34577     1/imm32/some-block-depth
    34578     0/imm32/no-stack-offset
    34579     0x11/imm32/alloc-id:fake
    34580     Any-register/imm32
    34581
    34582 Byte-var-in-some-register:  # (payload var)
    34583     0x11/imm32/alloc-id:fake:payload
    34584     0/imm32/name
    34585     0/imm32/name
    34586     0x11/imm32/alloc-id:fake
    34587     Type-byte/imm32
    34588     1/imm32/some-block-depth
    34589     0/imm32/no-stack-offset
    34590     0x11/imm32/alloc-id:fake
    34591     Any-register/imm32
    34592
    34593 Single-int-var-in-eax:  # (payload list var)
    34594     0x11/imm32/alloc-id:fake:payload
    34595     0x11/imm32/alloc-id:fake
    34596     Int-var-in-eax/imm32
    34597     0/imm32/next
    34598     0/imm32/next
    34599
    34600 Int-var-in-eax:
    34601     0x11/imm32/alloc-id:fake:payload
    34602     0/imm32/name
    34603     0/imm32/name
    34604     0x11/imm32/alloc-id:fake
    34605     Type-int/imm32
    34606     1/imm32/some-block-depth
    34607     0/imm32/no-stack-offset
    34608     0x11/imm32/alloc-id:fake
    34609     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
    34610
    34611 Single-int-var-in-ecx:  # (payload list var)
    34612     0x11/imm32/alloc-id:fake:payload
    34613     0x11/imm32/alloc-id:fake
    34614     Int-var-in-ecx/imm32
    34615     0/imm32/next
    34616     0/imm32/next
    34617
    34618 Int-var-in-ecx:
    34619     0x11/imm32/alloc-id:fake:payload
    34620     0/imm32/name
    34621     0/imm32/name
    34622     0x11/imm32/alloc-id:fake
    34623     Type-int/imm32
    34624     1/imm32/some-block-depth
    34625     0/imm32/no-stack-offset
    34626     0x11/imm32/alloc-id:fake
    34627     $Register-ecx/imm32/register
    34628
    34629 Single-int-var-in-edx:  # (payload list var)
    34630     0x11/imm32/alloc-id:fake:payload
    34631     0x11/imm32/alloc-id:fake
    34632     Int-var-in-edx/imm32
    34633     0/imm32/next
    34634     0/imm32/next
    34635
    34636 Int-var-in-edx:  # (payload list var)
    34637     0x11/imm32/alloc-id:fake:payload
    34638     0/imm32/name
    34639     0/imm32/name
    34640     0x11/imm32/alloc-id:fake
    34641     Type-int/imm32
    34642     1/imm32/some-block-depth
    34643     0/imm32/no-stack-offset
    34644     0x11/imm32/alloc-id:fake
    34645     $Register-edx/imm32/register
    34646
    34647 Single-int-var-in-ebx:  # (payload list var)
    34648     0x11/imm32/alloc-id:fake:payload
    34649     0x11/imm32/alloc-id:fake
    34650     Int-var-in-ebx/imm32
    34651     0/imm32/next
    34652     0/imm32/next
    34653
    34654 Int-var-in-ebx:  # (payload list var)
    34655     0x11/imm32/alloc-id:fake:payload
    34656     0/imm32/name
    34657     0/imm32/name
    34658     0x11/imm32/alloc-id:fake
    34659     Type-int/imm32
    34660     1/imm32/some-block-depth
    34661     0/imm32/no-stack-offset
    34662     0x11/imm32/alloc-id:fake
    34663     $Register-ebx/imm32/register
    34664
    34665 Single-int-var-in-esi:  # (payload list var)
    34666     0x11/imm32/alloc-id:fake:payload
    34667     0x11/imm32/alloc-id:fake
    34668     Int-var-in-esi/imm32
    34669     0/imm32/next
    34670     0/imm32/next
    34671
    34672 Int-var-in-esi:  # (payload list var)
    34673     0x11/imm32/alloc-id:fake:payload
    34674     0/imm32/name
    34675     0/imm32/name
    34676     0x11/imm32/alloc-id:fake
    34677     Type-int/imm32
    34678     1/imm32/some-block-depth
    34679     0/imm32/no-stack-offset
    34680     0x11/imm32/alloc-id:fake
    34681     $Register-esi/imm32/register
    34682
    34683 Single-int-var-in-edi:  # (payload list var)
    34684     0x11/imm32/alloc-id:fake:payload
    34685     0x11/imm32/alloc-id:fake
    34686     Int-var-in-edi/imm32
    34687     0/imm32/next
    34688     0/imm32/next
    34689
    34690 Int-var-in-edi:  # (payload list var)
    34691     0x11/imm32/alloc-id:fake:payload
    34692     0/imm32/name
    34693     0/imm32/name
    34694     0x11/imm32/alloc-id:fake
    34695     Type-int/imm32
    34696     1/imm32/some-block-depth
    34697     0/imm32/no-stack-offset
    34698     0x11/imm32/alloc-id:fake
    34699     $Register-edi/imm32/register
    34700
    34701 Single-lit-var:  # (payload list var)
    34702     0x11/imm32/alloc-id:fake:payload
    34703     0x11/imm32/alloc-id:fake
    34704     Lit-var/imm32
    34705     0/imm32/next
    34706     0/imm32/next
    34707
    34708 Lit-var:  # (payload var)
    34709     0x11/imm32/alloc-id:fake:payload
    34710     0/imm32/name
    34711     0/imm32/name
    34712     0x11/imm32/alloc-id:fake
    34713     Type-literal/imm32
    34714     1/imm32/some-block-depth
    34715     0/imm32/no-stack-offset
    34716     0/imm32/no-register
    34717     0/imm32/no-register
    34718
    34719 Single-float-var-in-mem:  # (payload list var)
    34720     0x11/imm32/alloc-id:fake:payload
    34721     0x11/imm32/alloc-id:fake
    34722     Float-var-in-mem/imm32
    34723     0/imm32/next
    34724     0/imm32/next
    34725
    34726 Float-var-in-mem:  # (payload var)
    34727     0x11/imm32/alloc-id:fake:payload
    34728     0/imm32/name
    34729     0/imm32/name
    34730     0x11/imm32/alloc-id:fake
    34731     Type-float/imm32
    34732     1/imm32/some-block-depth
    34733     1/imm32/some-stack-offset
    34734     0/imm32/no-register
    34735     0/imm32/no-register
    34736
    34737 Single-float-var-in-some-register:  # (payload list var)
    34738     0x11/imm32/alloc-id:fake:payload
    34739     0x11/imm32/alloc-id:fake
    34740     Float-var-in-some-register/imm32
    34741     0/imm32/next
    34742     0/imm32/next
    34743
    34744 Float-var-in-some-register:  # (payload var)
    34745     0x11/imm32/alloc-id:fake:payload
    34746     0/imm32/name
    34747     0/imm32/name
    34748     0x11/imm32/alloc-id:fake
    34749     Type-float/imm32
    34750     1/imm32/some-block-depth
    34751     0/imm32/no-stack-offset
    34752     0x11/imm32/alloc-id:fake
    34753     Any-register/imm32
    34754
    34755 Type-int:  # (payload type-tree)
    34756     0x11/imm32/alloc-id:fake:payload
    34757     1/imm32/is-atom
    34758     1/imm32/value:int
    34759     0/imm32/left:unused
    34760     0/imm32/right:null
    34761     0/imm32/right:null
    34762
    34763 Type-literal:  # (payload type-tree)
    34764     0x11/imm32/alloc-id:fake:payload
    34765     1/imm32/is-atom
    34766     0/imm32/value:literal
    34767     0/imm32/left:unused
    34768     0/imm32/right:null
    34769     0/imm32/right:null
    34770
    34771 Type-addr:  # (payload type-tree)
    34772     0x11/imm32/alloc-id:fake:payload
    34773     1/imm32/is-atom
    34774     2/imm32/value:addr
    34775     0/imm32/left:unused
    34776     0/imm32/right:null
    34777     0/imm32/right:null
    34778
    34779 Type-byte:  # (payload type-tree)
    34780     0x11/imm32/alloc-id:fake:payload
    34781     1/imm32/is-atom
    34782     8/imm32/value:byte
    34783     0/imm32/left:unused
    34784     0/imm32/right:null
    34785     0/imm32/right:null
    34786
    34787 Type-float:  # (payload type-tree)
    34788     0x11/imm32/alloc-id:fake:payload
    34789     1/imm32/is-atom
    34790     0xf/imm32/value:float
    34791     0/imm32/left:unused
    34792     0/imm32/right:null
    34793     0/imm32/right:null
    34794
    34795 == code
    34796 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
    34797     # . prologue
    34798     55/push-ebp
    34799     89/<- %ebp 4/r32/esp
    34800     # . save registers
    34801     50/push-eax
    34802     51/push-ecx
    34803     # ecx = primitive
    34804     8b/-> *(ebp+0x10) 1/r32/ecx
    34805     # emit primitive name
    34806     (emit-indent *(ebp+8) *Curr-block-depth)
    34807     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
    34808     (write-buffered *(ebp+8) %eax)
    34809     # emit rm32 if necessary
    34810     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
    34811     # emit xm32 if necessary
    34812     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
    34813     # emit r32 if necessary
    34814     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
    34815     # emit x32 if necessary
    34816     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
    34817     # emit imm32 if necessary
    34818     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
    34819     # emit imm8 if necessary
    34820     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
    34821     # emit disp32 if necessary
    34822     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
    34823     (write-buffered *(ebp+8) Newline)
    34824 $emit-subx-primitive:end:
    34825     # . restore registers
    34826     59/pop-to-ecx
    34827     58/pop-to-eax
    34828     # . epilogue
    34829     89/<- %esp 5/r32/ebp
    34830     5d/pop-to-ebp
    34831     c3/return
    34832
    34833 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    34834     # . prologue
    34835     55/push-ebp
    34836     89/<- %ebp 4/r32/esp
    34837     # . save registers
    34838     50/push-eax
    34839     # if (l == 0) return
    34840     81 7/subop/compare *(ebp+0xc) 0/imm32
    34841     74/jump-if-= $emit-subx-rm32:end/disp8
    34842     # var v/eax: (addr stmt-var)
    34843     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    34844     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    34845 $emit-subx-rm32:end:
    34846     # . restore registers
    34847     58/pop-to-eax
    34848     # . epilogue
    34849     89/<- %esp 5/r32/ebp
    34850     5d/pop-to-ebp
    34851     c3/return
    34852
    34853 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)
    34854     # . prologue
    34855     55/push-ebp
    34856     89/<- %ebp 4/r32/esp
    34857     # . save registers
    34858     51/push-ecx
    34859     # eax = l
    34860     8b/-> *(ebp+0xc) 0/r32/eax
    34861     # ecx = stmt
    34862     8b/-> *(ebp+8) 1/r32/ecx
    34863     # if (l == 1) return stmt->inouts
    34864     {
    34865       3d/compare-eax-and 1/imm32
    34866       75/jump-if-!= break/disp8
    34867 $get-stmt-operand-from-arg-location:1:
    34868       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    34869       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    34870     }
    34871     # if (l == 2) return stmt->inouts->next
    34872     {
    34873       3d/compare-eax-and 2/imm32
    34874       75/jump-if-!= break/disp8
    34875 $get-stmt-operand-from-arg-location:2:
    34876       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    34877       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    34878       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    34879     }
    34880     # if (l == 3) return stmt->outputs
    34881     {
    34882       3d/compare-eax-and 3/imm32
    34883       75/jump-if-!= break/disp8
    34884 $get-stmt-operand-from-arg-location:3:
    34885       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    34886       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    34887     }
    34888     # abort
    34889     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
    34890 $get-stmt-operand-from-arg-location:end:
    34891     # . restore registers
    34892     59/pop-to-ecx
    34893     # . epilogue
    34894     89/<- %esp 5/r32/ebp
    34895     5d/pop-to-ebp
    34896     c3/return
    34897
    34898 $get-stmt-operand-from-arg-location:abort:
    34899     # error("invalid arg-location " eax)
    34900     (write-buffered *(ebp+0x10) "invalid arg-location ")
    34901     (write-int32-hex-buffered *(ebp+0x10) %eax)
    34902     (write-buffered *(ebp+0x10) Newline)
    34903     (flush *(ebp+0x10))
    34904     (stop *(ebp+0x14) 1)
    34905     # never gets here
    34906
    34907 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    34908     # . prologue
    34909     55/push-ebp
    34910     89/<- %ebp 4/r32/esp
    34911     # . save registers
    34912     50/push-eax
    34913     51/push-ecx
    34914     # if (l == 0) return
    34915     81 7/subop/compare *(ebp+0xc) 0/imm32
    34916     0f 84/jump-if-= $emit-subx-r32:end/disp32
    34917     # var v/eax: (addr stmt-var)
    34918     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    34919     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    34920     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    34921 #?     (write-buffered Stderr "looking up ")
    34922 #?     (write-buffered Stderr %eax)
    34923 #?     (write-buffered Stderr Newline)
    34924 #?     (flush Stderr)
    34925     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    34926     (write-buffered *(ebp+8) Space)
    34927     (write-int32-hex-buffered *(ebp+8) *eax)
    34928     (write-buffered *(ebp+8) "/r32")
    34929 $emit-subx-r32:end:
    34930     # . restore registers
    34931     59/pop-to-ecx
    34932     58/pop-to-eax
    34933     # . epilogue
    34934     89/<- %esp 5/r32/ebp
    34935     5d/pop-to-ebp
    34936     c3/return
    34937
    34938 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    34939     # . prologue
    34940     55/push-ebp
    34941     89/<- %ebp 4/r32/esp
    34942     # . save registers
    34943     50/push-eax
    34944     51/push-ecx
    34945     # if (l == 0) return
    34946     81 7/subop/compare *(ebp+0xc) 0/imm32
    34947     0f 84/jump-if-= $emit-subx-x32:end/disp32
    34948     # var v/eax: (addr stmt-var)
    34949     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    34950     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    34951     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    34952 #?     (write-buffered Stderr "looking up ")
    34953 #?     (write-buffered Stderr %eax)
    34954 #?     (write-buffered Stderr Newline)
    34955 #?     (flush Stderr)
    34956     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    34957     (write-buffered *(ebp+8) Space)
    34958     (write-int32-hex-buffered *(ebp+8) *eax)
    34959     (write-buffered *(ebp+8) "/x32")
    34960 $emit-subx-x32:end:
    34961     # . restore registers
    34962     59/pop-to-ecx
    34963     58/pop-to-eax
    34964     # . epilogue
    34965     89/<- %esp 5/r32/ebp
    34966     5d/pop-to-ebp
    34967     c3/return
    34968
    34969 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    34970     # . prologue
    34971     55/push-ebp
    34972     89/<- %ebp 4/r32/esp
    34973     # . save registers
    34974     50/push-eax
    34975     51/push-ecx
    34976     # if (l == 0) return
    34977     81 7/subop/compare *(ebp+0xc) 0/imm32
    34978     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    34979     # var v/eax: (handle var)
    34980     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    34981     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    34982     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    34983     (write-buffered *(ebp+8) Space)
    34984     (write-buffered *(ebp+8) %eax)
    34985     (write-buffered *(ebp+8) "/imm32")
    34986 $emit-subx-imm32:end:
    34987     # . restore registers
    34988     59/pop-to-ecx
    34989     58/pop-to-eax
    34990     # . epilogue
    34991     89/<- %esp 5/r32/ebp
    34992     5d/pop-to-ebp
    34993     c3/return
    34994
    34995 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    34996     # . prologue
    34997     55/push-ebp
    34998     89/<- %ebp 4/r32/esp
    34999     # . save registers
    35000     50/push-eax
    35001     51/push-ecx
    35002     # if (l == 0) return
    35003     81 7/subop/compare *(ebp+0xc) 0/imm32
    35004     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35005     # var v/eax: (handle var)
    35006     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35007     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35008     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35009     (write-buffered *(ebp+8) Space)
    35010     (write-buffered *(ebp+8) %eax)
    35011     (write-buffered *(ebp+8) "/imm8")
    35012 $emit-subx-imm8:end:
    35013     # . restore registers
    35014     59/pop-to-ecx
    35015     58/pop-to-eax
    35016     # . epilogue
    35017     89/<- %esp 5/r32/ebp
    35018     5d/pop-to-ebp
    35019     c3/return
    35020
    35021 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    35022     # . prologue
    35023     55/push-ebp
    35024     89/<- %ebp 4/r32/esp
    35025     # . save registers
    35026     50/push-eax
    35027     51/push-ecx
    35028     # if (location == 0) return
    35029     81 7/subop/compare *(ebp+0xc) 0/imm32
    35030     0f 84/jump-if-= $emit-subx-disp32:end/disp32
    35031     # var v/eax: (addr stmt-var)
    35032     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    35033     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35034     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35035     (write-buffered *(ebp+8) Space)
    35036     (write-buffered *(ebp+8) %eax)
    35037     # hack: if instruction operation starts with "break", emit ":break"
    35038     # var name/ecx: (addr array byte) = lookup(stmt->operation)
    35039     8b/-> *(ebp+0x10) 0/r32/eax
    35040     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    35041     89/<- %ecx 0/r32/eax
    35042     {
    35043       (string-starts-with? %ecx "break")  # => eax
    35044       3d/compare-eax-and 0/imm32/false
    35045       74/jump-if-= break/disp8
    35046       (write-buffered *(ebp+8) ":break")
    35047     }
    35048     # hack: if instruction operation starts with "loop", emit ":loop"
    35049     {
    35050       (string-starts-with? %ecx "loop")  # => eax
    35051       3d/compare-eax-and 0/imm32/false
    35052       74/jump-if-= break/disp8
    35053       (write-buffered *(ebp+8) ":loop")
    35054     }
    35055     (write-buffered *(ebp+8) "/disp32")
    35056 $emit-subx-disp32:end:
    35057     # . restore registers
    35058     59/pop-to-ecx
    35059     58/pop-to-eax
    35060     # . epilogue
    35061     89/<- %esp 5/r32/ebp
    35062     5d/pop-to-ebp
    35063     c3/return
    35064
    35065 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
    35066     # . prologue
    35067     55/push-ebp
    35068     89/<- %ebp 4/r32/esp
    35069     # . save registers
    35070     50/push-eax
    35071     51/push-ecx
    35072     #
    35073     (emit-indent *(ebp+8) *Curr-block-depth)
    35074     (write-buffered *(ebp+8) "(")
    35075     # ecx = stmt
    35076     8b/-> *(ebp+0xc) 1/r32/ecx
    35077     # - emit function name
    35078     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35079     (write-buffered *(ebp+8) %eax)
    35080     # - emit arguments
    35081     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
    35082     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35083     {
    35084       # if (curr == null) break
    35085       3d/compare-eax-and 0/imm32
    35086       74/jump-if-= break/disp8
    35087       #
    35088       (emit-subx-call-operand *(ebp+8) %eax)
    35089       # curr = lookup(curr->next)
    35090       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35091       eb/jump loop/disp8
    35092     }
    35093     #
    35094     (write-buffered *(ebp+8) ")\n")
    35095 $emit-call:end:
    35096     # . restore registers
    35097     59/pop-to-ecx
    35098     58/pop-to-eax
    35099     # . epilogue
    35100     89/<- %esp 5/r32/ebp
    35101     5d/pop-to-ebp
    35102     c3/return
    35103
    35104 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
    35105     # shares code with emit-subx-var-as-rm32
    35106     # . prologue
    35107     55/push-ebp
    35108     89/<- %ebp 4/r32/esp
    35109     # . save registers
    35110     50/push-eax
    35111     51/push-ecx
    35112     56/push-esi
    35113     # ecx = s
    35114     8b/-> *(ebp+0xc) 1/r32/ecx
    35115     # var operand/esi: (addr var) = lookup(s->value)
    35116     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35117     89/<- %esi 0/r32/eax
    35118     # if (operand->register && !s->is-deref?) emit "%__"
    35119     {
    35120 $emit-subx-call-operand:check-for-register-direct:
    35121       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35122       74/jump-if-= break/disp8
    35123       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35124       75/jump-if-!= break/disp8
    35125 $emit-subx-call-operand:register-direct:
    35126       (write-buffered *(ebp+8) " %")
    35127       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35128       (write-buffered *(ebp+8) %eax)
    35129       e9/jump $emit-subx-call-operand:end/disp32
    35130     }
    35131     # else if (operand->register && s->is-deref?) emit "*__"
    35132     {
    35133 $emit-subx-call-operand:check-for-register-indirect:
    35134       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35135       74/jump-if-= break/disp8
    35136       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35137       74/jump-if-= break/disp8
    35138 $emit-subx-call-operand:register-indirect:
    35139       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
    35140       e9/jump $emit-subx-call-operand:end/disp32
    35141     }
    35142     # else if (operand->stack-offset) emit "*(ebp+__)"
    35143     {
    35144       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35145       74/jump-if-= break/disp8
    35146 $emit-subx-call-operand:stack:
    35147       (emit-subx-call-operand-stack *(ebp+8) %esi)
    35148       e9/jump $emit-subx-call-operand:end/disp32
    35149     }
    35150     # else if (operand->type == literal) emit "__"
    35151     {
    35152       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35153       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
    35154       75/jump-if-!= break/disp8
    35155 $emit-subx-call-operand:literal:
    35156       (write-buffered *(ebp+8) Space)
    35157       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35158       (write-buffered *(ebp+8) %eax)
    35159       e9/jump $emit-subx-call-operand:end/disp32
    35160     }
    35161     # else if (operand->type == literal-string) emit "__"
    35162     {
    35163       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35164       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
    35165       75/jump-if-!= break/disp8
    35166 $emit-subx-call-operand:literal-string:
    35167       (write-buffered *(ebp+8) Space)
    35168       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35169       (write-buffered *(ebp+8) %eax)
    35170     }
    35171 $emit-subx-call-operand:end:
    35172     # . restore registers
    35173     5e/pop-to-esi
    35174     59/pop-to-ecx
    35175     58/pop-to-eax
    35176     # . epilogue
    35177     89/<- %esp 5/r32/ebp
    35178     5d/pop-to-ebp
    35179     c3/return
    35180
    35181 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
    35182     # . prologue
    35183     55/push-ebp
    35184     89/<- %ebp 4/r32/esp
    35185     # . save registers
    35186     50/push-eax
    35187     51/push-ecx
    35188     56/push-esi
    35189     # esi = v
    35190     8b/-> *(ebp+0xc) 6/r32/esi
    35191     # var size/ecx: int = size-of-deref(v)
    35192     (size-of-deref %esi)  # => eax
    35193     89/<- %ecx 0/r32/eax
    35194     # var reg-name/esi: (addr array byte) = lookup(v->register)
    35195     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35196     89/<- %esi 0/r32/eax
    35197     # TODO: assert size is a multiple of 4
    35198     # var i/eax: int = 0
    35199     b8/copy-to-eax 0/imm32
    35200     {
    35201 $emit-subx-call-operand-register-indirect:loop:
    35202       # if (i >= size) break
    35203       39/compare %eax 1/r32/ecx
    35204       7d/jump-if->= break/disp8
    35205       # emit " *(" v->register "+" i ")"
    35206       (write-buffered *(ebp+8) " *(")
    35207       (write-buffered *(ebp+8) %esi)
    35208       (write-buffered *(ebp+8) "+")
    35209       (write-int32-hex-buffered *(ebp+8) %eax)
    35210       (write-buffered *(ebp+8) ")")
    35211       # i += 4
    35212       05/add-to-eax 4/imm32
    35213       #
    35214       eb/jump loop/disp8
    35215     }
    35216 $emit-subx-call-operand-register-indirect:end:
    35217     # . restore registers
    35218     5e/pop-to-esi
    35219     59/pop-to-ecx
    35220     58/pop-to-eax
    35221     # . epilogue
    35222     89/<- %esp 5/r32/ebp
    35223     5d/pop-to-ebp
    35224     c3/return
    35225
    35226 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
    35227     # . prologue
    35228     55/push-ebp
    35229     89/<- %ebp 4/r32/esp
    35230     # . save registers
    35231     50/push-eax
    35232     51/push-ecx
    35233     56/push-esi
    35234     # esi = v
    35235     8b/-> *(ebp+0xc) 6/r32/esi
    35236     # var curr/ecx: int = v->offset
    35237     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
    35238     # var max/eax: int = v->offset + size-of(v)
    35239     (size-of %esi)  # => eax
    35240     # TODO: assert size is a multiple of 4
    35241     01/add-to %eax 1/r32/ecx
    35242     {
    35243 $emit-subx-call-operand-stack:loop:
    35244       # if (curr >= max) break
    35245       39/compare %ecx 0/r32/eax
    35246       7d/jump-if->= break/disp8
    35247       # emit " *(ebp+" curr ")"
    35248       (write-buffered *(ebp+8) " *(ebp+")
    35249       (write-int32-hex-buffered *(ebp+8) %ecx)
    35250       (write-buffered *(ebp+8) ")")
    35251       # i += 4
    35252       81 0/subop/add %ecx 4/imm32
    35253       #
    35254       eb/jump loop/disp8
    35255     }
    35256 $emit-subx-call-operand-stack:end:
    35257     # . restore registers
    35258     5e/pop-to-esi
    35259     59/pop-to-ecx
    35260     58/pop-to-eax
    35261     # . epilogue
    35262     89/<- %esp 5/r32/ebp
    35263     5d/pop-to-ebp
    35264     c3/return
    35265
    35266 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
    35267     # . prologue
    35268     55/push-ebp
    35269     89/<- %ebp 4/r32/esp
    35270     # . save registers
    35271     50/push-eax
    35272     51/push-ecx
    35273     56/push-esi
    35274     # ecx = s
    35275     8b/-> *(ebp+0xc) 1/r32/ecx
    35276     # var operand/esi: (addr var) = lookup(s->value)
    35277     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35278     89/<- %esi 0/r32/eax
    35279     # if (operand->register && s->is-deref?) emit "*__"
    35280     {
    35281 $emit-subx-var-as-rm32:check-for-register-indirect:
    35282       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35283       74/jump-if-= break/disp8
    35284       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35285       74/jump-if-= break/disp8
    35286 $emit-subx-var-as-rm32:register-indirect:
    35287       (write-buffered *(ebp+8) " *")
    35288       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35289       (write-buffered *(ebp+8) %eax)
    35290       e9/jump $emit-subx-var-as-rm32:end/disp32
    35291     }
    35292     # if (operand->register && !s->is-deref?) emit "%__"
    35293     {
    35294 $emit-subx-var-as-rm32:check-for-register-direct:
    35295       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35296       74/jump-if-= break/disp8
    35297       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35298       75/jump-if-!= break/disp8
    35299 $emit-subx-var-as-rm32:register-direct:
    35300       (write-buffered *(ebp+8) " %")
    35301       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35302       (write-buffered *(ebp+8) %eax)
    35303       e9/jump $emit-subx-var-as-rm32:end/disp32
    35304     }
    35305     # else if (operand->stack-offset) emit "*(ebp+__)"
    35306     {
    35307       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35308       74/jump-if-= break/disp8
    35309 $emit-subx-var-as-rm32:stack:
    35310       (write-buffered *(ebp+8) Space)
    35311       (write-buffered *(ebp+8) "*(ebp+")
    35312       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
    35313       (write-buffered *(ebp+8) ")")
    35314     }
    35315 $emit-subx-var-as-rm32:end:
    35316     # . restore registers
    35317     5e/pop-to-esi
    35318     59/pop-to-ecx
    35319     58/pop-to-eax
    35320     # . epilogue
    35321     89/<- %esp 5/r32/ebp
    35322     5d/pop-to-ebp
    35323     c3/return
    35324
    35325 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
    35326     # . prologue
    35327     55/push-ebp
    35328     89/<- %ebp 4/r32/esp
    35329     # . save registers
    35330     51/push-ecx
    35331     # var curr/ecx: (addr primitive) = primitives
    35332     8b/-> *(ebp+8) 1/r32/ecx
    35333     {
    35334 $find-matching-primitive:loop:
    35335       # if (curr == null) break
    35336       81 7/subop/compare %ecx 0/imm32
    35337       74/jump-if-= break/disp8
    35338       # if match(curr, stmt) return curr
    35339       {
    35340         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
    35341         3d/compare-eax-and 0/imm32/false
    35342         74/jump-if-= break/disp8
    35343         89/<- %eax 1/r32/ecx
    35344         eb/jump $find-matching-primitive:end/disp8
    35345       }
    35346 $find-matching-primitive:next-primitive:
    35347       # curr = curr->next
    35348       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    35349       89/<- %ecx 0/r32/eax
    35350       #
    35351       e9/jump loop/disp32
    35352     }
    35353     # return null
    35354     b8/copy-to-eax 0/imm32
    35355 $find-matching-primitive:end:
    35356     # . restore registers
    35357     59/pop-to-ecx
    35358     # . epilogue
    35359     89/<- %esp 5/r32/ebp
    35360     5d/pop-to-ebp
    35361     c3/return
    35362
    35363 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
    35364     # A mu stmt matches a primitive if the name matches, all the inout vars
    35365     # match, and all the output vars match.
    35366     # Vars match if types match and registers match.
    35367     # In addition, a stmt output matches a primitive's output if types match
    35368     # and the primitive has a wildcard register.
    35369     # . prologue
    35370     55/push-ebp
    35371     89/<- %ebp 4/r32/esp
    35372     # . save registers
    35373     51/push-ecx
    35374     52/push-edx
    35375     53/push-ebx
    35376     56/push-esi
    35377     57/push-edi
    35378     # ecx = stmt
    35379     8b/-> *(ebp+8) 1/r32/ecx
    35380     # edx = primitive
    35381     8b/-> *(ebp+0xc) 2/r32/edx
    35382     {
    35383 $mu-stmt-matches-primitive?:check-name:
    35384       # if (primitive->name != stmt->operation) return false
    35385       # . var esi: (addr array byte) = lookup(stmt->operation)
    35386       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35387       89/<- %esi 0/r32/eax
    35388       # . var edi: (addr array byte) = lookup(primitive->name)
    35389       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
    35390 #?       (write-buffered Stderr %eax)
    35391 #?       (write-buffered Stderr Newline)
    35392 #?       (flush Stderr)
    35393       89/<- %edi 0/r32/eax
    35394       (string-equal? %esi %edi)  # => eax
    35395       3d/compare-eax-and 0/imm32/false
    35396       75/jump-if-!= break/disp8
    35397       b8/copy-to-eax 0/imm32
    35398       e9/jump $mu-stmt-matches-primitive?:end/disp32
    35399     }
    35400     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
    35401     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35402     89/<- %esi 0/r32/eax
    35403     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
    35404     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
    35405     89/<- %edi 0/r32/eax
    35406     {
    35407 $mu-stmt-matches-primitive?:inouts-loop:
    35408       # if (curr == 0 && curr2 == 0) move on to check outputs
    35409       {
    35410 $mu-stmt-matches-primitive?:check-both-inouts-null:
    35411         81 7/subop/compare %esi 0/imm32
    35412         75/jump-if-!= break/disp8
    35413 $mu-stmt-matches-primitive?:stmt-inout-null:
    35414         81 7/subop/compare %edi 0/imm32
    35415         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
    35416 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
    35417         # return false
    35418         b8/copy-to-eax 0/imm32/false
    35419         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35420       }
    35421       # if (curr2 == 0) return false
    35422       {
    35423 $mu-stmt-matches-primitive?:check-prim-inout-null:
    35424         81 7/subop/compare %edi 0/imm32
    35425         75/jump-if-!= break/disp8
    35426 $mu-stmt-matches-primitive?:prim-inout-null:
    35427         b8/copy-to-eax 0/imm32/false
    35428         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35429       }
    35430       # if (curr != curr2) return false
    35431       {
    35432 $mu-stmt-matches-primitive?:check-inouts-match:
    35433         (lookup *edi *(edi+4))  # List-value List-value => eax
    35434         (operand-matches-primitive? %esi %eax)  # => eax
    35435         3d/compare-eax-and 0/imm32/false
    35436         75/jump-if-!= break/disp8
    35437 $mu-stmt-matches-primitive?:inouts-match:
    35438         b8/copy-to-eax 0/imm32/false
    35439         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35440       }
    35441 $mu-stmt-matches-primitive?:next-inout:
    35442       # curr = lookup(curr->next)
    35443       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35444       89/<- %esi 0/r32/eax
    35445       # curr2 = lookup(curr2->next)
    35446       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35447       89/<- %edi 0/r32/eax
    35448       #
    35449       e9/jump loop/disp32
    35450     }
    35451 $mu-stmt-matches-primitive?:check-outputs:
    35452     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
    35453     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35454     89/<- %esi 0/r32/eax
    35455     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
    35456     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
    35457     89/<- %edi 0/r32/eax
    35458     {
    35459 $mu-stmt-matches-primitive?:outputs-loop:
    35460       # if (curr == 0) return (curr2 == 0)
    35461       {
    35462 $mu-stmt-matches-primitive?:check-both-outputs-null:
    35463         81 7/subop/compare %esi 0/imm32
    35464         75/jump-if-!= break/disp8
    35465         {
    35466 $mu-stmt-matches-primitive?:stmt-output-null:
    35467           81 7/subop/compare %edi 0/imm32
    35468           75/jump-if-!= break/disp8
    35469 $mu-stmt-matches-primitive?:both-outputs-null:
    35470           # return true
    35471           b8/copy-to-eax 1/imm32
    35472           e9/jump $mu-stmt-matches-primitive?:end/disp32
    35473         }
    35474 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
    35475         # return false
    35476         b8/copy-to-eax 0/imm32
    35477         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35478       }
    35479       # if (curr2 == 0) return false
    35480       {
    35481 $mu-stmt-matches-primitive?:check-prim-output-null:
    35482         81 7/subop/compare %edi 0/imm32
    35483         75/jump-if-!= break/disp8
    35484 $mu-stmt-matches-primitive?:prim-output-is-null:
    35485         b8/copy-to-eax 0/imm32
    35486         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35487       }
    35488       # if (curr != curr2) return false
    35489       {
    35490 $mu-stmt-matches-primitive?:check-outputs-match:
    35491         (lookup *edi *(edi+4))  # List-value List-value => eax
    35492         (operand-matches-primitive? %esi %eax)  # => eax
    35493         3d/compare-eax-and 0/imm32/false
    35494         75/jump-if-!= break/disp8
    35495 $mu-stmt-matches-primitive?:outputs-match:
    35496         b8/copy-to-eax 0/imm32
    35497         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35498       }
    35499 $mu-stmt-matches-primitive?:next-output:
    35500       # curr = lookup(curr->next)
    35501       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35502       89/<- %esi 0/r32/eax
    35503       # curr2 = lookup(curr2->next)
    35504       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35505       89/<- %edi 0/r32/eax
    35506       #
    35507       e9/jump loop/disp32
    35508     }
    35509 $mu-stmt-matches-primitive?:return-true:
    35510     b8/copy-to-eax 1/imm32
    35511 $mu-stmt-matches-primitive?:end:
    35512     # . restore registers
    35513     5f/pop-to-edi
    35514     5e/pop-to-esi
    35515     5b/pop-to-ebx
    35516     5a/pop-to-edx
    35517     59/pop-to-ecx
    35518     # . epilogue
    35519     89/<- %esp 5/r32/ebp
    35520     5d/pop-to-ebp
    35521     c3/return
    35522
    35523 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
    35524     # . prologue
    35525     55/push-ebp
    35526     89/<- %ebp 4/r32/esp
    35527     # . save registers
    35528     51/push-ecx
    35529     52/push-edx
    35530     53/push-ebx
    35531     56/push-esi
    35532     57/push-edi
    35533     # ecx = s
    35534     8b/-> *(ebp+8) 1/r32/ecx
    35535     # var var/esi: (addr var) = lookup(s->value)
    35536     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35537     89/<- %esi 0/r32/eax
    35538     # edi = prim-var
    35539     8b/-> *(ebp+0xc) 7/r32/edi
    35540 $operand-matches-primitive?:check-type:
    35541     # if !category-match?(var->type, prim-var->type) return false
    35542     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
    35543     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35544     89/<- %ebx 0/r32/eax
    35545     # . if s is deref, vtype = vtype->right
    35546     {
    35547       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35548       74/jump-if-= break/disp8
    35549 $operand-matches-primitive?:is-deref:
    35550       # . var t/eax: (addr type)
    35551       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    35552       # . if !t->is-atom? t = t->left
    35553       81 7/subop/compare *eax 0/imm32/false
    35554       {
    35555         75/jump-if-!= break/disp8
    35556         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35557       }
    35558       # .
    35559       89/<- %ebx 0/r32/eax
    35560     }
    35561     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
    35562     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    35563     (subx-type-category-match? %ebx %eax)  # => eax
    35564     3d/compare-eax-and 0/imm32/false
    35565     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
    35566     {
    35567 $operand-matches-primitive?:check-register:
    35568       # if prim-var is in memory and var is in register but dereference, match
    35569       {
    35570         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    35571         0f 85/jump-if-!= break/disp32
    35572         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35573         74/jump-if-= break/disp8
    35574         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35575         74/jump-if-= break/disp8
    35576 $operand-matches-primitive?:var-deref-match:
    35577         e9/jump $operand-matches-primitive?:return-true/disp32
    35578       }
    35579       # if prim-var is in register and var is in register but dereference, no match
    35580       {
    35581         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    35582         0f 84/jump-if-= break/disp32
    35583         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35584         0f 84/jump-if-= break/disp32
    35585         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35586         74/jump-if-= break/disp8
    35587 $operand-matches-primitive?:var-deref-no-match:
    35588         e9/jump $operand-matches-primitive?:return-false/disp32
    35589       }
    35590       # return false if var->register doesn't match prim-var->register
    35591       {
    35592         # if register addresses are equal, it's a match
    35593         # var vreg/ebx: (addr array byte) = lookup(var->register)
    35594         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35595         89/<- %ebx 0/r32/eax
    35596         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
    35597         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    35598         89/<- %ecx 0/r32/eax
    35599         # if (vreg == preg) break
    35600         39/compare %ecx 3/r32/ebx
    35601         74/jump-if-= break/disp8
    35602 $operand-matches-primitive?:var-register-no-match:
    35603         # if either address is 0, return false
    35604         81 7/subop/compare %ebx 0/imm32
    35605         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    35606         81 7/subop/compare %ecx 0/imm32
    35607         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    35608         # if prim-var->register is wildcard, it's a match
    35609         (string-equal? %ecx "*")  # Any-register => eax
    35610         3d/compare-eax-and 0/imm32/false
    35611         75/jump-if-!= break/disp8
    35612 $operand-matches-primitive?:wildcard-no-match:
    35613         # if string contents aren't equal, return false
    35614         (string-equal? %ecx %ebx)  # => eax
    35615         3d/compare-eax-and 0/imm32/false
    35616         74/jump-if-= $operand-matches-primitive?:return-false/disp8
    35617       }
    35618     }
    35619 $operand-matches-primitive?:return-true:
    35620     b8/copy-to-eax 1/imm32/true
    35621     eb/jump $operand-matches-primitive?:end/disp8
    35622 $operand-matches-primitive?:return-false:
    35623     b8/copy-to-eax 0/imm32/false
    35624 $operand-matches-primitive?:end:
    35625     # . restore registers
    35626     5f/pop-to-edi
    35627     5e/pop-to-esi
    35628     5b/pop-to-ebx
    35629     5a/pop-to-edx
    35630     59/pop-to-ecx
    35631     # . epilogue
    35632     89/<- %esp 5/r32/ebp
    35633     5d/pop-to-ebp
    35634     c3/return
    35635
    35636 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
    35637     # . prologue
    35638     55/push-ebp
    35639     89/<- %ebp 4/r32/esp
    35640     # . save registers
    35641     51/push-ecx
    35642     # var curr/ecx: (handle function) = functions
    35643     8b/-> *(ebp+8) 1/r32/ecx
    35644     {
    35645       # if (curr == null) break
    35646       81 7/subop/compare %ecx 0/imm32
    35647       74/jump-if-= break/disp8
    35648 #?       (write-buffered Stderr "iter\n")
    35649 #?       (flush Stderr)
    35650       # if match(stmt, curr) return curr
    35651       {
    35652         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
    35653         3d/compare-eax-and 0/imm32/false
    35654         74/jump-if-= break/disp8
    35655         89/<- %eax 1/r32/ecx
    35656         eb/jump $find-matching-function:end/disp8
    35657       }
    35658       # curr = curr->next
    35659       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    35660       89/<- %ecx 0/r32/eax
    35661       #
    35662       eb/jump loop/disp8
    35663     }
    35664     # return null
    35665     b8/copy-to-eax 0/imm32
    35666 $find-matching-function:end:
    35667     # . restore registers
    35668     59/pop-to-ecx
    35669     # . epilogue
    35670     89/<- %esp 5/r32/ebp
    35671     5d/pop-to-ebp
    35672     c3/return
    35673
    35674 # Just compare names; user-defined functions don't support overloading yet.
    35675 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
    35676     # . prologue
    35677     55/push-ebp
    35678     89/<- %ebp 4/r32/esp
    35679     # . save registers
    35680     51/push-ecx
    35681     # return function->name == stmt->operation
    35682     # ecx = lookup(stmt->operation)
    35683     8b/-> *(ebp+8) 0/r32/eax
    35684     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    35685     89/<- %ecx 0/r32/eax
    35686     # eax = lookup(function->name)
    35687     8b/-> *(ebp+0xc) 0/r32/eax
    35688     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    35689     (string-equal? %eax %ecx)  # => eax
    35690 $mu-stmt-matches-function?:end:
    35691     # . restore registers
    35692     59/pop-to-ecx
    35693     # . epilogue
    35694     89/<- %esp 5/r32/ebp
    35695     5d/pop-to-ebp
    35696     c3/return
    35697
    35698 # Type-checking happens elsewhere. This method is for selecting between
    35699 # primitives.
    35700 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    35701     # . prologue
    35702     55/push-ebp
    35703     89/<- %ebp 4/r32/esp
    35704     # . save registers
    35705     51/push-ecx
    35706     # var cata/ecx: int = type-category(a)
    35707     (type-category *(ebp+8))  # => eax
    35708     89/<- %ecx 0/r32/eax
    35709     # var catb/eax: int = type-category(b)
    35710     (type-category *(ebp+0xc))  # => eax
    35711     # return cata == catb
    35712     39/compare %eax 1/r32/ecx
    35713     0f 94/set-byte-if-= %al
    35714     81 4/subop/and %eax 0xff/imm32
    35715 $subx-type-category-match?:end:
    35716     # . restore registers
    35717     59/pop-to-ecx
    35718     # . epilogue
    35719     89/<- %esp 5/r32/ebp
    35720     5d/pop-to-ebp
    35721     c3/return
    35722
    35723 type-category:  # a: (addr type-tree) -> result/eax: int
    35724     # . prologue
    35725     55/push-ebp
    35726     89/<- %ebp 4/r32/esp
    35727     # . save registers
    35728     51/push-ecx
    35729     # var lit?/ecx: boolean = literal-type?(a)
    35730     (simple-mu-type? *(ebp+8) 0)  # literal => eax
    35731     89/<- %ecx 0/r32/eax
    35732     # var float?/eax: int = float?(a)
    35733     (simple-mu-type? *(ebp+8) 0xf)  # => eax
    35734     # set bits for lit? and float?
    35735     c1/shift 4/subop/left %ecx 1/imm8
    35736     09/or %eax 1/r32/ecx
    35737 $type-category:end:
    35738     # . restore registers
    35739     59/pop-to-ecx
    35740     # . epilogue
    35741     89/<- %esp 5/r32/ebp
    35742     5d/pop-to-ebp
    35743     c3/return
    35744
    35745 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
    35746     # . prologue
    35747     55/push-ebp
    35748     89/<- %ebp 4/r32/esp
    35749     # . save registers
    35750     51/push-ecx
    35751     # ecx = n
    35752     8b/-> *(ebp+0xc) 1/r32/ecx
    35753     # return (a->value == n)
    35754     8b/-> *(ebp+8) 0/r32/eax
    35755     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    35756     0f 94/set-byte-if-= %al
    35757     81 4/subop/and %eax 0xff/imm32
    35758 $simple-mu-type?:end:
    35759     # . restore registers
    35760     59/pop-to-ecx
    35761     # . epilogue
    35762     89/<- %esp 5/r32/ebp
    35763     5d/pop-to-ebp
    35764     c3/return
    35765
    35766 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
    35767     # . prologue
    35768     55/push-ebp
    35769     89/<- %ebp 4/r32/esp
    35770     # eax = a
    35771     8b/-> *(ebp+8) 0/r32/eax
    35772     # if (!a->is-atom?) a = a->left
    35773     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35774     {
    35775       75/jump-if-!= break/disp8
    35776       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35777     }
    35778     # return (a->value == addr)
    35779     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
    35780     0f 94/set-byte-if-= %al
    35781     81 4/subop/and %eax 0xff/imm32
    35782 $mu-addr-type?:end:
    35783     # . epilogue
    35784     89/<- %esp 5/r32/ebp
    35785     5d/pop-to-ebp
    35786     c3/return
    35787
    35788 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
    35789     # . prologue
    35790     55/push-ebp
    35791     89/<- %ebp 4/r32/esp
    35792     # eax = a
    35793     8b/-> *(ebp+8) 0/r32/eax
    35794     # if (!a->is-atom?) a = a->left
    35795     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35796     {
    35797       75/jump-if-!= break/disp8
    35798       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35799     }
    35800     # return (a->value == array)
    35801     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
    35802     0f 94/set-byte-if-= %al
    35803     81 4/subop/and %eax 0xff/imm32
    35804 $mu-array-type?:end:
    35805     # . epilogue
    35806     89/<- %esp 5/r32/ebp
    35807     5d/pop-to-ebp
    35808     c3/return
    35809
    35810 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
    35811     # . prologue
    35812     55/push-ebp
    35813     89/<- %ebp 4/r32/esp
    35814     # . save registers
    35815     56/push-esi
    35816     # esi = a
    35817     8b/-> *(ebp+8) 6/r32/esi
    35818     # if (a->is-atom?) return false
    35819     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
    35820     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
    35821     # if a is not an addr, return false
    35822     (mu-addr-type? %esi)  # => eax
    35823     3d/compare-eax-with 0/imm32/false
    35824     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
    35825     # if a is not an array, return false
    35826     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    35827     (mu-array-type? %eax)  # => eax
    35828     3d/compare-eax-with 0/imm32/false
    35829     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
    35830     # var p/eax: (addr type-tree) = payload of a
    35831     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    35832     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    35833     # if p is an atom, return false
    35834     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35835     75/jump-if-!= $mu-string-type?:return-false/disp8
    35836     # return (p == byte)
    35837     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35838     (simple-mu-type? %eax 8)  # byte => eax
    35839     eb/jump $mu-string-type?:end/disp8
    35840 $mu-string-type?:return-false:
    35841     b8/copy-to-eax 0/imm32/false
    35842 $mu-string-type?:end:
    35843     # . restore registers
    35844     5e/pop-to-esi
    35845     # . epilogue
    35846     89/<- %esp 5/r32/ebp
    35847     5d/pop-to-ebp
    35848     c3/return
    35849
    35850 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
    35851     # . prologue
    35852     55/push-ebp
    35853     89/<- %ebp 4/r32/esp
    35854     # eax = a
    35855     8b/-> *(ebp+8) 0/r32/eax
    35856     # if (!a->is-atom?) a = a->left
    35857     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35858     {
    35859       75/jump-if-!= break/disp8
    35860       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35861     }
    35862     # return (a->value == stream)
    35863     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
    35864     0f 94/set-byte-if-= %al
    35865     81 4/subop/and %eax 0xff/imm32
    35866 $mu-stream-type?:end:
    35867     # . epilogue
    35868     89/<- %esp 5/r32/ebp
    35869     5d/pop-to-ebp
    35870     c3/return
    35871
    35872 test-emit-subx-stmt-primitive:
    35873     # Primitive operation on a variable on the stack.
    35874     #   increment foo
    35875     # =>
    35876     #   ff 0/subop/increment *(ebp-8)
    35877     #
    35878     # There's a variable on the var stack as follows:
    35879     #   name: 'foo'
    35880     #   type: int
    35881     #   stack-offset: -8
    35882     #
    35883     # There's a primitive with this info:
    35884     #   name: 'increment'
    35885     #   inouts: int/mem
    35886     #   value: 'ff 0/subop/increment'
    35887     #
    35888     # . prologue
    35889     55/push-ebp
    35890     89/<- %ebp 4/r32/esp
    35891     # setup
    35892     (clear-stream _test-output-stream)
    35893     (clear-stream $_test-output-buffered-file->buffer)
    35894     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
    35895 $test-emit-subx-stmt-primitive:initialize-type:
    35896     # var type/ecx: (payload type-tree) = int
    35897     68/push 0/imm32/right:null
    35898     68/push 0/imm32/right:null
    35899     68/push 0/imm32/left:unused
    35900     68/push 1/imm32/value:int
    35901     68/push 1/imm32/is-atom?:true
    35902     68/push 0x11/imm32/alloc-id:fake:payload
    35903     89/<- %ecx 4/r32/esp
    35904 $test-emit-subx-stmt-primitive:initialize-var:
    35905     # var var-foo/ecx: (payload var) = var(type)
    35906     68/push 0/imm32/no-register
    35907     68/push 0/imm32/no-register
    35908     68/push -8/imm32/stack-offset
    35909     68/push 1/imm32/block-depth
    35910     51/push-ecx/type
    35911     68/push 0x11/imm32/alloc-id:fake
    35912     68/push 0/imm32/name
    35913     68/push 0/imm32/name
    35914     68/push 0x11/imm32/alloc-id:fake:payload
    35915     89/<- %ecx 4/r32/esp
    35916 $test-emit-subx-stmt-primitive:initialize-var-name:
    35917     # var-foo->name = "foo"
    35918     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    35919     (copy-array Heap "foo" %eax)
    35920 $test-emit-subx-stmt-primitive:initialize-stmt-var:
    35921     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    35922     68/push 0/imm32/is-deref:false
    35923     68/push 0/imm32/next
    35924     68/push 0/imm32/next
    35925     51/push-ecx/var-foo
    35926     68/push 0x11/imm32/alloc-id:fake
    35927     68/push 0x11/imm32/alloc-id:fake:payload
    35928     89/<- %ebx 4/r32/esp
    35929 $test-emit-subx-stmt-primitive:initialize-stmt:
    35930     # var stmt/esi: (addr statement)
    35931     68/push 0/imm32/no-outputs
    35932     68/push 0/imm32/no-outputs
    35933     53/push-ebx/inouts
    35934     68/push 0x11/imm32/alloc-id:fake
    35935     68/push 0/imm32/operation
    35936     68/push 0/imm32/operation
    35937     68/push 1/imm32/tag
    35938     89/<- %esi 4/r32/esp
    35939 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
    35940     # stmt->operation = "increment"
    35941     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    35942     (copy-array Heap "increment" %eax)
    35943 $test-emit-subx-stmt-primitive:initialize-primitive:
    35944     # var primitives/ebx: (addr primitive)
    35945     68/push 0/imm32/next
    35946     68/push 0/imm32/next
    35947     68/push 0/imm32/no-x32
    35948     68/push 0/imm32/no-xm32
    35949     68/push 0/imm32/no-disp32
    35950     68/push 0/imm32/no-imm8
    35951     68/push 0/imm32/no-imm32
    35952     68/push 0/imm32/no-r32
    35953     68/push 1/imm32/rm32-is-first-inout
    35954     68/push 0/imm32/subx-name
    35955     68/push 0/imm32/subx-name
    35956     68/push 0/imm32/no-outputs
    35957     68/push 0/imm32/no-outputs
    35958     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    35959     68/push 0x11/imm32/alloc-id:fake
    35960     68/push 0/imm32/name
    35961     68/push 0/imm32/name
    35962     89/<- %ebx 4/r32/esp
    35963 $test-emit-subx-stmt-primitive:initialize-primitive-name:
    35964     # primitives->name = "increment"
    35965     (copy-array Heap "increment" %ebx)  # Primitive-name
    35966 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
    35967     # primitives->subx-name = "ff 0/subop/increment"
    35968     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    35969     (copy-array Heap "ff 0/subop/increment" %eax)
    35970     # convert
    35971     c7 0/subop/copy *Curr-block-depth 0/imm32
    35972     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    35973     (flush _test-output-buffered-file)
    35974 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    35980     # check output
    35981     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
    35982     # . epilogue
    35983     89/<- %esp 5/r32/ebp
    35984     5d/pop-to-ebp
    35985     c3/return
    35986
    35987 test-emit-subx-stmt-primitive-register:
    35988     # Primitive operation on a variable in a register.
    35989     #   foo <- increment
    35990     # =>
    35991     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    35992     #
    35993     # There's a variable on the var stack as follows:
    35994     #   name: 'foo'
    35995     #   type: int
    35996     #   register: 'eax'
    35997     #
    35998     # There's a primitive with this info:
    35999     #   name: 'increment'
    36000     #   out: int/reg
    36001     #   value: 'ff 0/subop/increment'
    36002     #
    36003     # . prologue
    36004     55/push-ebp
    36005     89/<- %ebp 4/r32/esp
    36006     # setup
    36007     (clear-stream _test-output-stream)
    36008     (clear-stream $_test-output-buffered-file->buffer)
    36009 $test-emit-subx-stmt-primitive-register:initialize-type:
    36010     # var type/ecx: (payload type-tree) = int
    36011     68/push 0/imm32/right:null
    36012     68/push 0/imm32/right:null
    36013     68/push 0/imm32/left:unused
    36014     68/push 1/imm32/value:int
    36015     68/push 1/imm32/is-atom?:true
    36016     68/push 0x11/imm32/alloc-id:fake:payload
    36017     89/<- %ecx 4/r32/esp
    36018 $test-emit-subx-stmt-primitive-register:initialize-var:
    36019     # var var-foo/ecx: (payload var)
    36020     68/push 0/imm32/register
    36021     68/push 0/imm32/register
    36022     68/push 0/imm32/no-stack-offset
    36023     68/push 1/imm32/block-depth
    36024     51/push-ecx
    36025     68/push 0x11/imm32/alloc-id:fake
    36026     68/push 0/imm32/name
    36027     68/push 0/imm32/name
    36028     68/push 0x11/imm32/alloc-id:fake:payload
    36029     89/<- %ecx 4/r32/esp
    36030 $test-emit-subx-stmt-primitive-register:initialize-var-name:
    36031     # var-foo->name = "foo"
    36032     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36033     (copy-array Heap "foo" %eax)
    36034 $test-emit-subx-stmt-primitive-register:initialize-var-register:
    36035     # var-foo->register = "eax"
    36036     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36037     (copy-array Heap "eax" %eax)
    36038 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
    36039     # var operand/ebx: (payload stmt-var)
    36040     68/push 0/imm32/is-deref:false
    36041     68/push 0/imm32/next
    36042     68/push 0/imm32/next
    36043     51/push-ecx/var-foo
    36044     68/push 0x11/imm32/alloc-id:fake
    36045     68/push 0x11/imm32/alloc-id:fake:payload
    36046     89/<- %ebx 4/r32/esp
    36047 $test-emit-subx-stmt-primitive-register:initialize-stmt:
    36048     # var stmt/esi: (addr statement)
    36049     53/push-ebx/outputs
    36050     68/push 0x11/imm32/alloc-id:fake
    36051     68/push 0/imm32/no-inouts
    36052     68/push 0/imm32/no-inouts
    36053     68/push 0/imm32/operation
    36054     68/push 0/imm32/operation
    36055     68/push 1/imm32
    36056     89/<- %esi 4/r32/esp
    36057 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
    36058     # stmt->operation = "increment"
    36059     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36060     (copy-array Heap "increment" %eax)
    36061 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
    36062     # var formal-var/ebx: (payload var)
    36063     68/push 0/imm32/register
    36064     68/push 0/imm32/register
    36065     68/push 0/imm32/no-stack-offset
    36066     68/push 1/imm32/block-depth
    36067     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36068     68/push 0x11/imm32/alloc-id:fake
    36069     68/push 0/imm32/name
    36070     68/push 0/imm32/name
    36071     68/push 0x11/imm32/alloc-id:fake:payload
    36072     89/<- %ebx 4/r32/esp
    36073 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
    36074     # formal-var->name = "dummy"
    36075     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36076     (copy-array Heap "dummy" %eax)
    36077 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
    36078     # formal-var->register = "*"
    36079     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36080     (copy-array Heap "*" %eax)  # Any-register
    36081 $test-emit-subx-stmt-primitive-register:initialize-var-list:
    36082     # var formal-outputs/ebx: (payload list var)
    36083     68/push 0/imm32/next
    36084     68/push 0/imm32/next
    36085     53/push-ebx/formal-var
    36086     68/push 0x11/imm32/alloc-id:fake
    36087     68/push 0x11/imm32/alloc-id:fake:payload
    36088     89/<- %ebx 4/r32/esp
    36089 $test-emit-subx-stmt-primitive-register:initialize-primitive:
    36090     # var primitives/ebx: (addr primitive)
    36091     68/push 0/imm32/next
    36092     68/push 0/imm32/next
    36093     68/push 0/imm32/no-x32
    36094     68/push 0/imm32/no-xm32
    36095     68/push 0/imm32/no-disp32
    36096     68/push 0/imm32/no-imm8
    36097     68/push 0/imm32/no-imm32
    36098     68/push 0/imm32/no-r32
    36099     68/push 3/imm32/rm32-is-first-output
    36100     68/push 0/imm32/subx-name
    36101     68/push 0/imm32/subx-name
    36102     53/push-ebx/outputs
    36103     68/push 0x11/imm32/alloc-id:fake
    36104     68/push 0/imm32/no-inouts
    36105     68/push 0/imm32/no-inouts
    36106     68/push 0/imm32/name
    36107     68/push 0/imm32/name
    36108     89/<- %ebx 4/r32/esp
    36109 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
    36110     # primitives->name = "increment"
    36111     (copy-array Heap "increment" %ebx)  # Primitive-name
    36112 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
    36113     # primitives->subx-name = "ff 0/subop/increment"
    36114     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36115     (copy-array Heap "ff 0/subop/increment" %eax)
    36116     # convert
    36117     c7 0/subop/copy *Curr-block-depth 0/imm32
    36118     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36119     (flush _test-output-buffered-file)
    36120 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36126     # check output
    36127     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
    36128     # . epilogue
    36129     89/<- %esp 5/r32/ebp
    36130     5d/pop-to-ebp
    36131     c3/return
    36132
    36133 test-emit-subx-stmt-select-primitive:
    36134     # Select the right primitive between overloads.
    36135     #   foo <- increment
    36136     # =>
    36137     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36138     #
    36139     # There's a variable on the var stack as follows:
    36140     #   name: 'foo'
    36141     #   type: int
    36142     #   register: 'eax'
    36143     #
    36144     # There's two primitives, as follows:
    36145     #   - name: 'increment'
    36146     #     out: int/reg
    36147     #     value: 'ff 0/subop/increment'
    36148     #   - name: 'increment'
    36149     #     inout: int/mem
    36150     #     value: 'ff 0/subop/increment'
    36151     #
    36152     # . prologue
    36153     55/push-ebp
    36154     89/<- %ebp 4/r32/esp
    36155     # setup
    36156     (clear-stream _test-output-stream)
    36157     (clear-stream $_test-output-buffered-file->buffer)
    36158 $test-emit-subx-stmt-select-primitive:initialize-type:
    36159     # var type/ecx: (payload type-tree) = int
    36160     68/push 0/imm32/right:null
    36161     68/push 0/imm32/right:null
    36162     68/push 0/imm32/left:unused
    36163     68/push 1/imm32/value:int
    36164     68/push 1/imm32/is-atom?:true
    36165     68/push 0x11/imm32/alloc-id:fake:payload
    36166     89/<- %ecx 4/r32/esp
    36167 $test-emit-subx-stmt-select-primitive:initialize-var:
    36168     # var var-foo/ecx: (payload var)
    36169     68/push 0/imm32/register
    36170     68/push 0/imm32/register
    36171     68/push 0/imm32/no-stack-offset
    36172     68/push 1/imm32/block-depth
    36173     51/push-ecx
    36174     68/push 0x11/imm32/alloc-id:fake
    36175     68/push 0/imm32/name
    36176     68/push 0/imm32/name
    36177     68/push 0x11/imm32/alloc-id:fake:payload
    36178     89/<- %ecx 4/r32/esp
    36179 $test-emit-subx-stmt-select-primitive:initialize-var-name:
    36180     # var-foo->name = "foo"
    36181     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36182     (copy-array Heap "foo" %eax)
    36183 $test-emit-subx-stmt-select-primitive:initialize-var-register:
    36184     # var-foo->register = "eax"
    36185     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36186     (copy-array Heap "eax" %eax)
    36187 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
    36188     # var operand/ebx: (payload stmt-var)
    36189     68/push 0/imm32/is-deref:false
    36190     68/push 0/imm32/next
    36191     68/push 0/imm32/next
    36192     51/push-ecx/var-foo
    36193     68/push 0x11/imm32/alloc-id:fake
    36194     68/push 0x11/imm32/alloc-id:fake:payload
    36195     89/<- %ebx 4/r32/esp
    36196 $test-emit-subx-stmt-select-primitive:initialize-stmt:
    36197     # var stmt/esi: (addr statement)
    36198     53/push-ebx/outputs
    36199     68/push 0x11/imm32/alloc-id:fake
    36200     68/push 0/imm32/no-inouts
    36201     68/push 0/imm32/no-inouts
    36202     68/push 0/imm32/operation
    36203     68/push 0/imm32/operation
    36204     68/push 1/imm32
    36205     89/<- %esi 4/r32/esp
    36206 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
    36207     # stmt->operation = "increment"
    36208     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36209     (copy-array Heap "increment" %eax)
    36210 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
    36211     # var formal-var/ebx: (payload var)
    36212     68/push 0/imm32/register
    36213     68/push 0/imm32/register
    36214     68/push 0/imm32/no-stack-offset
    36215     68/push 1/imm32/block-depth
    36216     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36217     68/push 0x11/imm32/alloc-id:fake
    36218     68/push 0/imm32/name
    36219     68/push 0/imm32/name
    36220     68/push 0x11/imm32/alloc-id:fake:payload
    36221     89/<- %ebx 4/r32/esp
    36222 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
    36223     # formal-var->name = "dummy"
    36224     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36225     (copy-array Heap "dummy" %eax)
    36226 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
    36227     # formal-var->register = "*"
    36228     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36229     (copy-array Heap "*" %eax)  # Any-register
    36230 $test-emit-subx-stmt-select-primitive:initialize-var-list:
    36231     # var formal-outputs/ebx: (payload list var)
    36232     68/push 0/imm32/next
    36233     68/push 0/imm32/next
    36234     53/push-ebx/formal-var
    36235     68/push 0x11/imm32/alloc-id:fake
    36236     68/push 0x11/imm32/alloc-id:fake:payload
    36237     89/<- %ebx 4/r32/esp
    36238 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
    36239     # var primitive2/edi: (payload primitive)
    36240     68/push 0/imm32/next
    36241     68/push 0/imm32/next
    36242     68/push 0/imm32/no-x32
    36243     68/push 0/imm32/no-xm32
    36244     68/push 0/imm32/no-disp32
    36245     68/push 0/imm32/no-imm8
    36246     68/push 0/imm32/no-imm32
    36247     68/push 0/imm32/no-r32
    36248     68/push 3/imm32/rm32-is-first-output
    36249     68/push 0/imm32/subx-name
    36250     68/push 0/imm32/subx-name
    36251     53/push-ebx/outputs
    36252     68/push 0x11/imm32/alloc-id:fake
    36253     68/push 0/imm32/no-inouts
    36254     68/push 0/imm32/no-inouts
    36255     68/push 0/imm32/name
    36256     68/push 0/imm32/name
    36257     68/push 0x11/imm32/alloc-id:fake:payload
    36258     89/<- %edi 4/r32/esp
    36259 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
    36260     # primitives->name = "increment"
    36261     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36262     (copy-array Heap "increment" %eax)
    36263 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
    36264     # primitives->subx-name = "ff 0/subop/increment"
    36265     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36266     (copy-array Heap "ff 0/subop/increment" %eax)
    36267 $test-emit-subx-stmt-select-primitive:initialize-primitive:
    36268     # var primitives/ebx: (addr primitive)
    36269     57/push-edi
    36270     68/push 0x11/imm32/alloc-id:fake
    36271     68/push 0/imm32/no-x32
    36272     68/push 0/imm32/no-xm32
    36273     68/push 0/imm32/no-disp32
    36274     68/push 0/imm32/no-imm8
    36275     68/push 0/imm32/no-imm32
    36276     68/push 0/imm32/no-r32
    36277     68/push 1/imm32/rm32-is-first-inout
    36278     68/push 0/imm32/subx-name
    36279     68/push 0/imm32/subx-name
    36280     68/push 0/imm32/no-outputs
    36281     68/push 0/imm32/no-outputs
    36282     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36283     68/push 0x11/imm32/alloc-id:fake
    36284     68/push 0/imm32/name
    36285     68/push 0/imm32/name
    36286     89/<- %ebx 4/r32/esp
    36287 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
    36288     # primitives->name = "increment"
    36289     (copy-array Heap "increment" %ebx)  # Primitive-name
    36290 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
    36291     # primitives->subx-name = "ff 0/subop/increment"
    36292     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36293     (copy-array Heap "ff 0/subop/increment" %eax)
    36294     # convert
    36295     c7 0/subop/copy *Curr-block-depth 0/imm32
    36296     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36297     (flush _test-output-buffered-file)
    36298 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36304     # check output
    36305     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
    36306     # . epilogue
    36307     89/<- %esp 5/r32/ebp
    36308     5d/pop-to-ebp
    36309     c3/return
    36310
    36311 test-emit-subx-stmt-select-primitive-2:
    36312     # Select the right primitive between overloads.
    36313     #   increment foo
    36314     # =>
    36315     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36316     #
    36317     # There's a variable on the var stack as follows:
    36318     #   name: 'foo'
    36319     #   type: int
    36320     #   register: 'eax'
    36321     #
    36322     # There's two primitives, as follows:
    36323     #   - name: 'increment'
    36324     #     out: int/reg
    36325     #     value: 'ff 0/subop/increment'
    36326     #   - name: 'increment'
    36327     #     inout: int/mem
    36328     #     value: 'ff 0/subop/increment'
    36329     #
    36330     # . prologue
    36331     55/push-ebp
    36332     89/<- %ebp 4/r32/esp
    36333     # setup
    36334     (clear-stream _test-output-stream)
    36335     (clear-stream $_test-output-buffered-file->buffer)
    36336 $test-emit-subx-stmt-select-primitive-2:initialize-type:
    36337     # var type/ecx: (payload type-tree) = int
    36338     68/push 0/imm32/right:null
    36339     68/push 0/imm32/right:null
    36340     68/push 0/imm32/left:unused
    36341     68/push 1/imm32/value:int
    36342     68/push 1/imm32/is-atom?:true
    36343     68/push 0x11/imm32/alloc-id:fake:payload
    36344     89/<- %ecx 4/r32/esp
    36345 $test-emit-subx-stmt-select-primitive-2:initialize-var:
    36346     # var var-foo/ecx: (payload var)
    36347     68/push 0/imm32/register
    36348     68/push 0/imm32/register
    36349     68/push 0/imm32/no-stack-offset
    36350     68/push 1/imm32/block-depth
    36351     51/push-ecx
    36352     68/push 0x11/imm32/alloc-id:fake
    36353     68/push 0/imm32/name
    36354     68/push 0/imm32/name
    36355     68/push 0x11/imm32/alloc-id:fake:payload
    36356     89/<- %ecx 4/r32/esp
    36357 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
    36358     # var-foo->name = "foo"
    36359     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36360     (copy-array Heap "foo" %eax)
    36361 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
    36362     # var-foo->register = "eax"
    36363     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36364     (copy-array Heap "eax" %eax)
    36365 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
    36366     # var operand/ebx: (payload stmt-var)
    36367     68/push 0/imm32/is-deref:false
    36368     68/push 0/imm32/next
    36369     68/push 0/imm32/next
    36370     51/push-ecx/var-foo
    36371     68/push 0x11/imm32/alloc-id:fake
    36372     68/push 0x11/imm32/alloc-id:fake:payload
    36373     89/<- %ebx 4/r32/esp
    36374 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
    36375     # var stmt/esi: (addr statement)
    36376     68/push 0/imm32/no-outputs
    36377     68/push 0/imm32/no-outputs
    36378     53/push-ebx/inouts
    36379     68/push 0x11/imm32/alloc-id:fake
    36380     68/push 0/imm32/operation
    36381     68/push 0/imm32/operation
    36382     68/push 1/imm32
    36383     89/<- %esi 4/r32/esp
    36384 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
    36385     # stmt->operation = "increment"
    36386     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36387     (copy-array Heap "increment" %eax)
    36388 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
    36389     # var formal-var/ebx: (payload var)
    36390     68/push 0/imm32/register
    36391     68/push 0/imm32/register
    36392     68/push 0/imm32/no-stack-offset
    36393     68/push 1/imm32/block-depth
    36394     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36395     68/push 0x11/imm32/alloc-id:fake
    36396     68/push 0/imm32/name
    36397     68/push 0/imm32/name
    36398     68/push 0x11/imm32/alloc-id:fake:payload
    36399     89/<- %ebx 4/r32/esp
    36400 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
    36401     # formal-var->name = "dummy"
    36402     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36403     (copy-array Heap "dummy" %eax)
    36404 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
    36405     # formal-var->register = "*"
    36406     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36407     (copy-array Heap "*" %eax)  # Any-register
    36408 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
    36409     # var formal-outputs/ebx: (payload list stmt-var)
    36410     68/push 0/imm32/next
    36411     68/push 0/imm32/next
    36412     53/push-ebx/formal-var
    36413     68/push 0x11/imm32/alloc-id:fake
    36414     68/push 0x11/imm32/alloc-id:fake:payload
    36415     89/<- %ebx 4/r32/esp
    36416 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
    36417     # var primitive2/edi: (payload primitive)
    36418     68/push 0/imm32/next
    36419     68/push 0/imm32/next
    36420     68/push 0/imm32/no-x32
    36421     68/push 0/imm32/no-xm32
    36422     68/push 0/imm32/no-disp32
    36423     68/push 0/imm32/no-imm8
    36424     68/push 0/imm32/no-imm32
    36425     68/push 0/imm32/no-r32
    36426     68/push 3/imm32/rm32-is-first-output
    36427     68/push 0/imm32/subx-name
    36428     68/push 0/imm32/subx-name
    36429     53/push-ebx/outputs
    36430     68/push 0x11/imm32/alloc-id:fake
    36431     68/push 0/imm32/no-inouts
    36432     68/push 0/imm32/no-inouts
    36433     68/push 0/imm32/name
    36434     68/push 0/imm32/name
    36435     68/push 0x11/imm32/alloc-id:fake:payload
    36436     89/<- %edi 4/r32/esp
    36437 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
    36438     # primitives->name = "increment"
    36439     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36440     (copy-array Heap "increment" %eax)
    36441 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
    36442     # primitives->subx-name = "ff 0/subop/increment"
    36443     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36444     (copy-array Heap "ff 0/subop/increment" %eax)
    36445 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
    36446     # var primitives/ebx: (addr primitive)
    36447     57/push-edi
    36448     68/push 0x11/imm32/alloc-id:fake
    36449     68/push 0/imm32/no-x32
    36450     68/push 0/imm32/no-xm32
    36451     68/push 0/imm32/no-disp32
    36452     68/push 0/imm32/no-imm8
    36453     68/push 0/imm32/no-imm32
    36454     68/push 0/imm32/no-r32
    36455     68/push 1/imm32/rm32-is-first-inout
    36456     68/push 0/imm32/subx-name
    36457     68/push 0/imm32/subx-name
    36458     68/push 0/imm32/no-outputs
    36459     68/push 0/imm32/no-outputs
    36460     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36461     68/push 0x11/imm32/alloc-id:fake
    36462     68/push 0/imm32/name
    36463     68/push 0/imm32/name
    36464     89/<- %ebx 4/r32/esp
    36465 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
    36466     # primitives->name = "increment"
    36467     (copy-array Heap "increment" %ebx)  # Primitive-name
    36468 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
    36469     # primitives->subx-name = "ff 0/subop/increment"
    36470     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36471     (copy-array Heap "ff 0/subop/increment" %eax)
    36472     # convert
    36473     c7 0/subop/copy *Curr-block-depth 0/imm32
    36474     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36475     (flush _test-output-buffered-file)
    36476 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36482     # check output
    36483     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
    36484     # . epilogue
    36485     89/<- %esp 5/r32/ebp
    36486     5d/pop-to-ebp
    36487     c3/return
    36488
    36489 test-increment-register:
    36490     # Select the right register between overloads.
    36491     #   foo <- increment
    36492     # =>
    36493     #   50/increment-eax
    36494     #
    36495     # There's a variable on the var stack as follows:
    36496     #   name: 'foo'
    36497     #   type: int
    36498     #   register: 'eax'
    36499     #
    36500     # Primitives are the global definitions.
    36501     #
    36502     # . prologue
    36503     55/push-ebp
    36504     89/<- %ebp 4/r32/esp
    36505     # setup
    36506     (clear-stream _test-output-stream)
    36507     (clear-stream $_test-output-buffered-file->buffer)
    36508 $test-increment-register:initialize-type:
    36509     # var type/ecx: (payload type-tree) = int
    36510     68/push 0/imm32/right:null
    36511     68/push 0/imm32/right:null
    36512     68/push 0/imm32/left:unused
    36513     68/push 1/imm32/value:int
    36514     68/push 1/imm32/is-atom?:true
    36515     68/push 0x11/imm32/alloc-id:fake:payload
    36516     89/<- %ecx 4/r32/esp
    36517 $test-increment-register:initialize-var:
    36518     # var var-foo/ecx: (payload var)
    36519     68/push 0/imm32/register
    36520     68/push 0/imm32/register
    36521     68/push 0/imm32/no-stack-offset
    36522     68/push 1/imm32/block-depth
    36523     51/push-ecx
    36524     68/push 0x11/imm32/alloc-id:fake
    36525     68/push 0/imm32/name
    36526     68/push 0/imm32/name
    36527     68/push 0x11/imm32/alloc-id:fake:payload
    36528     89/<- %ecx 4/r32/esp
    36529 $test-increment-register:initialize-var-name:
    36530     # var-foo->name = "foo"
    36531     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36532     (copy-array Heap "foo" %eax)
    36533 $test-increment-register:initialize-var-register:
    36534     # var-foo->register = "eax"
    36535     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36536     (copy-array Heap "eax" %eax)
    36537 $test-increment-register:initialize-stmt-var:
    36538     # var operand/ebx: (payload stmt-var)
    36539     68/push 0/imm32/is-deref:false
    36540     68/push 0/imm32/next
    36541     68/push 0/imm32/next
    36542     51/push-ecx/var-foo
    36543     68/push 0x11/imm32/alloc-id:fake
    36544     68/push 0x11/imm32/alloc-id:fake:payload
    36545     89/<- %ebx 4/r32/esp
    36546 $test-increment-register:initialize-stmt:
    36547     # var stmt/esi: (addr statement)
    36548     53/push-ebx/outputs
    36549     68/push 0x11/imm32/alloc-id:fake
    36550     68/push 0/imm32/no-inouts
    36551     68/push 0/imm32/no-inouts
    36552     68/push 0/imm32/operation
    36553     68/push 0/imm32/operation
    36554     68/push 1/imm32
    36555     89/<- %esi 4/r32/esp
    36556 $test-increment-register:initialize-stmt-operation:
    36557     # stmt->operation = "increment"
    36558     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36559     (copy-array Heap "increment" %eax)
    36560     # convert
    36561     c7 0/subop/copy *Curr-block-depth 0/imm32
    36562     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36563     (flush _test-output-buffered-file)
    36564 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36570     # check output
    36571     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
    36572     # . epilogue
    36573     89/<- %esp 5/r32/ebp
    36574     5d/pop-to-ebp
    36575     c3/return
    36576
    36577 test-add-reg-to-reg:
    36578     #   var1/reg <- add var2/reg
    36579     # =>
    36580     #   01/add-to %var1 var2
    36581     #
    36582     # . prologue
    36583     55/push-ebp
    36584     89/<- %ebp 4/r32/esp
    36585     # setup
    36586     (clear-stream _test-output-stream)
    36587     (clear-stream $_test-output-buffered-file->buffer)
    36588 $test-add-reg-to-reg:initialize-type:
    36589     # var type/ecx: (payload type-tree) = int
    36590     68/push 0/imm32/right:null
    36591     68/push 0/imm32/right:null
    36592     68/push 0/imm32/left:unused
    36593     68/push 1/imm32/value:int
    36594     68/push 1/imm32/is-atom?:true
    36595     68/push 0x11/imm32/alloc-id:fake:payload
    36596     89/<- %ecx 4/r32/esp
    36597 $test-add-reg-to-reg:initialize-var1:
    36598     # var var1/ecx: (payload var)
    36599     68/push 0/imm32/register
    36600     68/push 0/imm32/register
    36601     68/push 0/imm32/no-stack-offset
    36602     68/push 1/imm32/block-depth
    36603     51/push-ecx
    36604     68/push 0x11/imm32/alloc-id:fake
    36605     68/push 0/imm32/name
    36606     68/push 0/imm32/name
    36607     68/push 0x11/imm32/alloc-id:fake:payload
    36608     89/<- %ecx 4/r32/esp
    36609 $test-add-reg-to-reg:initialize-var1-name:
    36610     # var1->name = "var1"
    36611     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36612     (copy-array Heap "var1" %eax)
    36613 $test-add-reg-to-reg:initialize-var1-register:
    36614     # var1->register = "eax"
    36615     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36616     (copy-array Heap "eax" %eax)
    36617 $test-add-reg-to-reg:initialize-var2:
    36618     # var var2/edx: (payload var)
    36619     68/push 0/imm32/register
    36620     68/push 0/imm32/register
    36621     68/push 0/imm32/no-stack-offset
    36622     68/push 1/imm32/block-depth
    36623     ff 6/subop/push *(ecx+0x10)
    36624     68/push 0x11/imm32/alloc-id:fake
    36625     68/push 0/imm32/name
    36626     68/push 0/imm32/name
    36627     68/push 0x11/imm32/alloc-id:fake:payload
    36628     89/<- %edx 4/r32/esp
    36629 $test-add-reg-to-reg:initialize-var2-name:
    36630     # var2->name = "var2"
    36631     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36632     (copy-array Heap "var2" %eax)
    36633 $test-add-reg-to-reg:initialize-var2-register:
    36634     # var2->register = "ecx"
    36635     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    36636     (copy-array Heap "ecx" %eax)
    36637 $test-add-reg-to-reg:initialize-inouts:
    36638     # var inouts/esi: (payload stmt-var) = [var2]
    36639     68/push 0/imm32/is-deref:false
    36640     68/push 0/imm32/next
    36641     68/push 0/imm32/next
    36642     52/push-edx/var2
    36643     68/push 0x11/imm32/alloc-id:fake
    36644     68/push 0x11/imm32/alloc-id:fake:payload
    36645     89/<- %esi 4/r32/esp
    36646 $test-add-reg-to-reg:initialize-outputs:
    36647     # var outputs/edi: (payload stmt-var) = [var1]
    36648     68/push 0/imm32/is-deref:false
    36649     68/push 0/imm32/next
    36650     68/push 0/imm32/next
    36651     51/push-ecx/var1
    36652     68/push 0x11/imm32/alloc-id:fake
    36653     68/push 0x11/imm32/alloc-id:fake:payload
    36654     89/<- %edi 4/r32/esp
    36655 $test-add-reg-to-reg:initialize-stmt:
    36656     # var stmt/esi: (addr statement)
    36657     68/push 0/imm32/next
    36658     68/push 0/imm32/next
    36659     57/push-edi/outputs
    36660     68/push 0x11/imm32/alloc-id:fake
    36661     56/push-esi/inouts
    36662     68/push 0x11/imm32/alloc-id:fake
    36663     68/push 0/imm32/operation
    36664     68/push 0/imm32/operation
    36665     68/push 1/imm32/tag:stmt1
    36666     89/<- %esi 4/r32/esp
    36667 $test-add-reg-to-reg:initialize-stmt-operation:
    36668     # stmt->operation = "add"
    36669     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36670     (copy-array Heap "add" %eax)
    36671     # convert
    36672     c7 0/subop/copy *Curr-block-depth 0/imm32
    36673     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36674     (flush _test-output-buffered-file)
    36675 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36681     # check output
    36682     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
    36683     # . epilogue
    36684     89/<- %esp 5/r32/ebp
    36685     5d/pop-to-ebp
    36686     c3/return
    36687
    36688 test-add-reg-to-mem:
    36689     #   add-to var1 var2/reg
    36690     # =>
    36691     #   01/add-to *(ebp+__) var2
    36692     #
    36693     # . prologue
    36694     55/push-ebp
    36695     89/<- %ebp 4/r32/esp
    36696     # setup
    36697     (clear-stream _test-output-stream)
    36698     (clear-stream $_test-output-buffered-file->buffer)
    36699 $test-add-reg-to-mem:initialize-type:
    36700     # var type/ecx: (payload type-tree) = int
    36701     68/push 0/imm32/right:null
    36702     68/push 0/imm32/right:null
    36703     68/push 0/imm32/left:unused
    36704     68/push 1/imm32/value:int
    36705     68/push 1/imm32/is-atom?:true
    36706     68/push 0x11/imm32/alloc-id:fake:payload
    36707     89/<- %ecx 4/r32/esp
    36708 $test-add-reg-to-mem:initialize-var1:
    36709     # var var1/ecx: (payload var)
    36710     68/push 0/imm32/register
    36711     68/push 0/imm32/register
    36712     68/push 8/imm32/stack-offset
    36713     68/push 1/imm32/block-depth
    36714     51/push-ecx
    36715     68/push 0x11/imm32/alloc-id:fake
    36716     68/push 0/imm32/name
    36717     68/push 0/imm32/name
    36718     68/push 0x11/imm32/alloc-id:fake:payload
    36719     89/<- %ecx 4/r32/esp
    36720 $test-add-reg-to-mem:initialize-var1-name:
    36721     # var1->name = "var1"
    36722     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36723     (copy-array Heap "var1" %eax)
    36724 $test-add-reg-to-mem:initialize-var2:
    36725     # var var2/edx: (payload var)
    36726     68/push 0/imm32/register
    36727     68/push 0/imm32/register
    36728     68/push 0/imm32/no-stack-offset
    36729     68/push 1/imm32/block-depth
    36730     ff 6/subop/push *(ecx+0x10)
    36731     68/push 0x11/imm32/alloc-id:fake
    36732     68/push 0/imm32/name
    36733     68/push 0/imm32/name
    36734     68/push 0x11/imm32/alloc-id:fake:payload
    36735     89/<- %edx 4/r32/esp
    36736 $test-add-reg-to-mem:initialize-var2-name:
    36737     # var2->name = "var2"
    36738     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36739     (copy-array Heap "var2" %eax)
    36740 $test-add-reg-to-mem:initialize-var2-register:
    36741     # var2->register = "ecx"
    36742     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    36743     (copy-array Heap "ecx" %eax)
    36744 $test-add-reg-to-mem:initialize-inouts:
    36745     # var inouts/esi: (payload stmt-var) = [var2]
    36746     68/push 0/imm32/is-deref:false
    36747     68/push 0/imm32/next
    36748     68/push 0/imm32/next
    36749     52/push-edx/var2
    36750     68/push 0x11/imm32/alloc-id:fake
    36751     68/push 0x11/imm32/alloc-id:fake:payload
    36752     89/<- %esi 4/r32/esp
    36753     # inouts = [var1, var2]
    36754     68/push 0/imm32/is-deref:false
    36755     56/push-esi/next
    36756     68/push 0x11/imm32/alloc-id:fake
    36757     51/push-ecx/var1
    36758     68/push 0x11/imm32/alloc-id:fake
    36759     68/push 0x11/imm32/alloc-id:fake:payload
    36760     89/<- %esi 4/r32/esp
    36761 $test-add-reg-to-mem:initialize-stmt:
    36762     # var stmt/esi: (addr statement)
    36763     68/push 0/imm32/next
    36764     68/push 0/imm32/next
    36765     68/push 0/imm32/outputs
    36766     68/push 0/imm32/outputs
    36767     56/push-esi/inouts
    36768     68/push 0x11/imm32/alloc-id:fake
    36769     68/push 0/imm32/operation
    36770     68/push 0/imm32/operation
    36771     68/push 1/imm32/tag:stmt1
    36772     89/<- %esi 4/r32/esp
    36773 $test-add-reg-to-mem:initialize-stmt-operation:
    36774     # stmt->operation = "add-to"
    36775     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36776     (copy-array Heap "add-to" %eax)
    36777     # convert
    36778     c7 0/subop/copy *Curr-block-depth 0/imm32
    36779     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36780     (flush _test-output-buffered-file)
    36781 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36787     # check output
    36788     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
    36789     # . epilogue
    36790     89/<- %esp 5/r32/ebp
    36791     5d/pop-to-ebp
    36792     c3/return
    36793
    36794 test-add-mem-to-reg:
    36795     #   var1/reg <- add var2
    36796     # =>
    36797     #   03/add *(ebp+__) var1
    36798     #
    36799     # . prologue
    36800     55/push-ebp
    36801     89/<- %ebp 4/r32/esp
    36802     # setup
    36803     (clear-stream _test-output-stream)
    36804     (clear-stream $_test-output-buffered-file->buffer)
    36805 $test-add-mem-to-reg:initialize-type:
    36806     # var type/ecx: (payload type-tree) = int
    36807     68/push 0/imm32/right:null
    36808     68/push 0/imm32/right:null
    36809     68/push 0/imm32/left:unused
    36810     68/push 1/imm32/value:int
    36811     68/push 1/imm32/is-atom?:true
    36812     68/push 0x11/imm32/alloc-id:fake:payload
    36813     89/<- %ecx 4/r32/esp
    36814 $test-add-mem-to-reg:initialize-var:
    36815     # var var1/ecx: (payload var)
    36816     68/push 0/imm32/register
    36817     68/push 0/imm32/register
    36818     68/push 0/imm32/no-stack-offset
    36819     68/push 1/imm32/block-depth
    36820     51/push-ecx
    36821     68/push 0x11/imm32/alloc-id:fake
    36822     68/push 0/imm32/name
    36823     68/push 0/imm32/name
    36824     68/push 0x11/imm32/alloc-id:fake:payload
    36825     89/<- %ecx 4/r32/esp
    36826 $test-add-mem-to-reg:initialize-var-name:
    36827     # var1->name = "foo"
    36828     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36829     (copy-array Heap "var1" %eax)
    36830 $test-add-mem-to-reg:initialize-var-register:
    36831     # var1->register = "eax"
    36832     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36833     (copy-array Heap "eax" %eax)
    36834 $test-add-mem-to-reg:initialize-var2:
    36835     # var var2/edx: (payload var)
    36836     68/push 0/imm32/register
    36837     68/push 0/imm32/register
    36838     68/push 8/imm32/stack-offset
    36839     68/push 1/imm32/block-depth
    36840     ff 6/subop/push *(ecx+0x10)
    36841     68/push 0x11/imm32/alloc-id:fake
    36842     68/push 0/imm32/name
    36843     68/push 0/imm32/name
    36844     68/push 0x11/imm32/alloc-id:fake:payload
    36845     89/<- %edx 4/r32/esp
    36846 $test-add-mem-to-reg:initialize-var2-name:
    36847     # var2->name = "var2"
    36848     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36849     (copy-array Heap "var2" %eax)
    36850 $test-add-mem-to-reg:initialize-inouts:
    36851     # var inouts/esi: (payload stmt-var) = [var2]
    36852     68/push 0/imm32/is-deref:false
    36853     68/push 0/imm32/next
    36854     68/push 0/imm32/next
    36855     52/push-edx/var2
    36856     68/push 0x11/imm32/alloc-id:fake
    36857     68/push 0x11/imm32/alloc-id:fake:payload
    36858     89/<- %esi 4/r32/esp
    36859 $test-add-mem-to-reg:initialize-outputs:
    36860     # var outputs/edi: (payload stmt-var) = [var1]
    36861     68/push 0/imm32/is-deref:false
    36862     68/push 0/imm32/next
    36863     68/push 0/imm32/next
    36864     51/push-ecx/var1
    36865     68/push 0x11/imm32/alloc-id:fake
    36866     68/push 0x11/imm32/alloc-id:fake:payload
    36867     89/<- %edi 4/r32/esp
    36868 $test-add-mem-to-reg:initialize-stmt:
    36869     # var stmt/esi: (addr statement)
    36870     68/push 0/imm32/next
    36871     68/push 0/imm32/next
    36872     57/push-edi/outputs
    36873     68/push 0x11/imm32/alloc-id:fake
    36874     56/push-esi/inouts
    36875     68/push 0x11/imm32/alloc-id:fake
    36876     68/push 0/imm32/operation
    36877     68/push 0/imm32/operation
    36878     68/push 1/imm32/tag:stmt1
    36879     89/<- %esi 4/r32/esp
    36880 $test-add-mem-to-reg:initialize-stmt-operation:
    36881     # stmt->operation = "add"
    36882     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36883     (copy-array Heap "add" %eax)
    36884     # convert
    36885     c7 0/subop/copy *Curr-block-depth 0/imm32
    36886     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36887     (flush _test-output-buffered-file)
    36888 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36894     # check output
    36895     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
    36896     # . epilogue
    36897     89/<- %esp 5/r32/ebp
    36898     5d/pop-to-ebp
    36899     c3/return
    36900
    36901 test-add-literal-to-eax:
    36902     #   var1/eax <- add 0x34
    36903     # =>
    36904     #   05/add-to-eax 0x34/imm32
    36905     #
    36906     # . prologue
    36907     55/push-ebp
    36908     89/<- %ebp 4/r32/esp
    36909     # setup
    36910     (clear-stream _test-output-stream)
    36911     (clear-stream $_test-output-buffered-file->buffer)
    36912 $test-add-literal-to-eax:initialize-var-type:
    36913     # var type/ecx: (payload type-tree) = int
    36914     68/push 0/imm32/right:null
    36915     68/push 0/imm32/right:null
    36916     68/push 0/imm32/left:unused
    36917     68/push 1/imm32/value:int
    36918     68/push 1/imm32/is-atom?:true
    36919     68/push 0x11/imm32/alloc-id:fake:payload
    36920     89/<- %ecx 4/r32/esp
    36921 $test-add-literal-to-eax:initialize-var:
    36922     # var v/ecx: (payload var)
    36923     68/push 0/imm32/register
    36924     68/push 0/imm32/register
    36925     68/push 0/imm32/no-stack-offset
    36926     68/push 1/imm32/block-depth
    36927     51/push-ecx
    36928     68/push 0x11/imm32/alloc-id:fake
    36929     68/push 0/imm32/name
    36930     68/push 0/imm32/name
    36931     68/push 0x11/imm32/alloc-id:fake:payload
    36932     89/<- %ecx 4/r32/esp
    36933 $test-add-literal-to-eax:initialize-var-name:
    36934     # v->name = "v"
    36935     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36936     (copy-array Heap "v" %eax)
    36937 $test-add-literal-to-eax:initialize-var-register:
    36938     # v->register = "eax"
    36939     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36940     (copy-array Heap "eax" %eax)
    36941 $test-add-literal-to-eax:initialize-literal-type:
    36942     # var type/edx: (payload type-tree) = literal
    36943     68/push 0/imm32/right:null
    36944     68/push 0/imm32/right:null
    36945     68/push 0/imm32/left:unused
    36946     68/push 0/imm32/value:literal
    36947     68/push 1/imm32/is-atom?:true
    36948     68/push 0x11/imm32/alloc-id:fake:payload
    36949     89/<- %edx 4/r32/esp
    36950 $test-add-literal-to-eax:initialize-literal:
    36951     # var l/edx: (payload var)
    36952     68/push 0/imm32/register
    36953     68/push 0/imm32/register
    36954     68/push 0/imm32/no-stack-offset
    36955     68/push 1/imm32/block-depth
    36956     52/push-edx
    36957     68/push 0x11/imm32/alloc-id:fake
    36958     68/push 0/imm32/name
    36959     68/push 0/imm32/name
    36960     68/push 0x11/imm32/alloc-id:fake:payload
    36961     89/<- %edx 4/r32/esp
    36962 $test-add-literal-to-eax:initialize-literal-value:
    36963     # l->name = "0x34"
    36964     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36965     (copy-array Heap "0x34" %eax)
    36966 $test-add-literal-to-eax:initialize-inouts:
    36967     # var inouts/esi: (payload stmt-var) = [l]
    36968     68/push 0/imm32/is-deref:false
    36969     68/push 0/imm32/next
    36970     68/push 0/imm32/next
    36971     52/push-edx/l
    36972     68/push 0x11/imm32/alloc-id:fake
    36973     68/push 0x11/imm32/alloc-id:fake:payload
    36974     89/<- %esi 4/r32/esp
    36975 $test-add-literal-to-eax:initialize-outputs:
    36976     # var outputs/edi: (payload stmt-var) = [v]
    36977     68/push 0/imm32/is-deref:false
    36978     68/push 0/imm32/next
    36979     68/push 0/imm32/next
    36980     51/push-ecx/v
    36981     68/push 0x11/imm32/alloc-id:fake
    36982     68/push 0x11/imm32/alloc-id:fake:payload
    36983     89/<- %edi 4/r32/esp
    36984 $test-add-literal-to-eax:initialize-stmt:
    36985     # var stmt/esi: (addr statement)
    36986     68/push 0/imm32/next
    36987     68/push 0/imm32/next
    36988     57/push-edi/outputs
    36989     68/push 0x11/imm32/alloc-id:fake
    36990     56/push-esi/inouts
    36991     68/push 0x11/imm32/alloc-id:fake
    36992     68/push 0/imm32/operation
    36993     68/push 0/imm32/operation
    36994     68/push 1/imm32/tag:stmt1
    36995     89/<- %esi 4/r32/esp
    36996 $test-add-literal-to-eax:initialize-stmt-operation:
    36997     # stmt->operation = "add"
    36998     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36999     (copy-array Heap "add" %eax)
    37000     # convert
    37001     c7 0/subop/copy *Curr-block-depth 0/imm32
    37002     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37003     (flush _test-output-buffered-file)
    37004 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37010     # check output
    37011     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
    37012     # . epilogue
    37013     89/<- %esp 5/r32/ebp
    37014     5d/pop-to-ebp
    37015     c3/return
    37016
    37017 test-add-literal-to-reg:
    37018     #   var1/ecx <- add 0x34
    37019     # =>
    37020     #   81 0/subop/add %ecx 0x34/imm32
    37021     #
    37022     # . prologue
    37023     55/push-ebp
    37024     89/<- %ebp 4/r32/esp
    37025     # setup
    37026     (clear-stream _test-output-stream)
    37027     (clear-stream $_test-output-buffered-file->buffer)
    37028 $test-add-literal-to-reg:initialize-var-type:
    37029     # var type/ecx: (payload type-tree) = int
    37030     68/push 0/imm32/right:null
    37031     68/push 0/imm32/right:null
    37032     68/push 0/imm32/left:unused
    37033     68/push 1/imm32/value:int
    37034     68/push 1/imm32/is-atom?:true
    37035     68/push 0x11/imm32/alloc-id:fake:payload
    37036     89/<- %ecx 4/r32/esp
    37037 $test-add-literal-to-reg:initialize-var:
    37038     # var v/ecx: (payload var)
    37039     68/push 0/imm32/register
    37040     68/push 0/imm32/register
    37041     68/push 0/imm32/no-stack-offset
    37042     68/push 1/imm32/block-depth
    37043     51/push-ecx
    37044     68/push 0x11/imm32/alloc-id:fake
    37045     68/push 0/imm32/name
    37046     68/push 0/imm32/name
    37047     68/push 0x11/imm32/alloc-id:fake:payload
    37048     89/<- %ecx 4/r32/esp
    37049 $test-add-literal-to-reg:initialize-var-name:
    37050     # v->name = "v"
    37051     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37052     (copy-array Heap "v" %eax)
    37053 $test-add-literal-to-reg:initialize-var-register:
    37054     # v->register = "ecx"
    37055     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37056     (copy-array Heap "ecx" %eax)
    37057 $test-add-literal-to-reg:initialize-literal-type:
    37058     # var type/edx: (payload type-tree) = literal
    37059     68/push 0/imm32/right:null
    37060     68/push 0/imm32/right:null
    37061     68/push 0/imm32/left:unused
    37062     68/push 0/imm32/value:literal
    37063     68/push 1/imm32/is-atom?:true
    37064     68/push 0x11/imm32/alloc-id:fake:payload
    37065     89/<- %edx 4/r32/esp
    37066 $test-add-literal-to-reg:initialize-literal:
    37067     # var l/edx: (payload var)
    37068     68/push 0/imm32/register
    37069     68/push 0/imm32/register
    37070     68/push 0/imm32/no-stack-offset
    37071     68/push 1/imm32/block-depth
    37072     52/push-edx
    37073     68/push 0x11/imm32/alloc-id:fake
    37074     68/push 0/imm32/name
    37075     68/push 0/imm32/name
    37076     68/push 0x11/imm32/alloc-id:fake:payload
    37077     89/<- %edx 4/r32/esp
    37078 $test-add-literal-to-reg:initialize-literal-value:
    37079     # l->name = "0x34"
    37080     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37081     (copy-array Heap "0x34" %eax)
    37082 $test-add-literal-to-reg:initialize-inouts:
    37083     # var inouts/esi: (payload stmt-var) = [l]
    37084     68/push 0/imm32/is-deref:false
    37085     68/push 0/imm32/next
    37086     68/push 0/imm32/next
    37087     52/push-edx/l
    37088     68/push 0x11/imm32/alloc-id:fake
    37089     68/push 0x11/imm32/alloc-id:fake:payload
    37090     89/<- %esi 4/r32/esp
    37091 $test-add-literal-to-reg:initialize-outputs:
    37092     # var outputs/edi: (payload stmt-var) = [v]
    37093     68/push 0/imm32/is-deref:false
    37094     68/push 0/imm32/next
    37095     68/push 0/imm32/next
    37096     51/push-ecx/v
    37097     68/push 0x11/imm32/alloc-id:fake
    37098     68/push 0x11/imm32/alloc-id:fake:payload
    37099     89/<- %edi 4/r32/esp
    37100 $test-add-literal-to-reg:initialize-stmt:
    37101     # var stmt/esi: (addr statement)
    37102     68/push 0/imm32/next
    37103     68/push 0/imm32/next
    37104     57/push-edi/outputs
    37105     68/push 0x11/imm32/alloc-id:fake
    37106     56/push-esi/inouts
    37107     68/push 0x11/imm32/alloc-id:fake
    37108     68/push 0/imm32/operation
    37109     68/push 0/imm32/operation
    37110     68/push 1/imm32/tag:stmt1
    37111     89/<- %esi 4/r32/esp
    37112 $test-add-literal-to-reg:initialize-stmt-operation:
    37113     # stmt->operation = "add"
    37114     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37115     (copy-array Heap "add" %eax)
    37116     # convert
    37117     c7 0/subop/copy *Curr-block-depth 0/imm32
    37118     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37119     (flush _test-output-buffered-file)
    37120 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37126     # check output
    37127     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
    37128     # . epilogue
    37129     89/<- %esp 5/r32/ebp
    37130     5d/pop-to-ebp
    37131     c3/return
    37132
    37133 test-add-literal-to-mem:
    37134     #   add-to var1, 0x34
    37135     # =>
    37136     #   81 0/subop/add %eax 0x34/imm32
    37137     #
    37138     # . prologue
    37139     55/push-ebp
    37140     89/<- %ebp 4/r32/esp
    37141     # setup
    37142     (clear-stream _test-output-stream)
    37143     (clear-stream $_test-output-buffered-file->buffer)
    37144 $test-add-literal-to-mem:initialize-type:
    37145     # var type/ecx: (payload type-tree) = int
    37146     68/push 0/imm32/right:null
    37147     68/push 0/imm32/right:null
    37148     68/push 0/imm32/left:unused
    37149     68/push 1/imm32/value:int
    37150     68/push 1/imm32/is-atom?:true
    37151     68/push 0x11/imm32/alloc-id:fake:payload
    37152     89/<- %ecx 4/r32/esp
    37153 $test-add-literal-to-mem:initialize-var1:
    37154     # var var1/ecx: (payload var)
    37155     68/push 0/imm32/register
    37156     68/push 0/imm32/register
    37157     68/push 8/imm32/stack-offset
    37158     68/push 1/imm32/block-depth
    37159     51/push-ecx
    37160     68/push 0x11/imm32/alloc-id:fake
    37161     68/push 0/imm32/name
    37162     68/push 0/imm32/name
    37163     68/push 0x11/imm32/alloc-id:fake:payload
    37164     89/<- %ecx 4/r32/esp
    37165 $test-add-literal-to-mem:initialize-var1-name:
    37166     # var1->name = "var1"
    37167     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37168     (copy-array Heap "var1" %eax)
    37169 $test-add-literal-to-mem:initialize-literal-type:
    37170     # var type/edx: (payload type-tree) = literal
    37171     68/push 0/imm32/right:null
    37172     68/push 0/imm32/right:null
    37173     68/push 0/imm32/left:unused
    37174     68/push 0/imm32/value:literal
    37175     68/push 1/imm32/is-atom?:true
    37176     68/push 0x11/imm32/alloc-id:fake:payload
    37177     89/<- %edx 4/r32/esp
    37178 $test-add-literal-to-mem:initialize-literal:
    37179     # var l/edx: (payload var)
    37180     68/push 0/imm32/register
    37181     68/push 0/imm32/register
    37182     68/push 0/imm32/no-stack-offset
    37183     68/push 1/imm32/block-depth
    37184     52/push-edx
    37185     68/push 0x11/imm32/alloc-id:fake
    37186     68/push 0/imm32/name
    37187     68/push 0/imm32/name
    37188     68/push 0x11/imm32/alloc-id:fake:payload
    37189     89/<- %edx 4/r32/esp
    37190 $test-add-literal-to-mem:initialize-literal-value:
    37191     # l->name = "0x34"
    37192     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37193     (copy-array Heap "0x34" %eax)
    37194 $test-add-literal-to-mem:initialize-inouts:
    37195     # var inouts/esi: (payload stmt-var) = [l]
    37196     68/push 0/imm32/is-deref:false
    37197     68/push 0/imm32/next
    37198     68/push 0/imm32/next
    37199     52/push-edx/l
    37200     68/push 0x11/imm32/alloc-id:fake
    37201     68/push 0x11/imm32/alloc-id:fake:payload
    37202     89/<- %esi 4/r32/esp
    37203     # var inouts = (handle stmt-var) = [var1, var2]
    37204     68/push 0/imm32/is-deref:false
    37205     56/push-esi/next
    37206     68/push 0x11/imm32/alloc-id:fake
    37207     51/push-ecx/var1
    37208     68/push 0x11/imm32/alloc-id:fake
    37209     68/push 0x11/imm32/alloc-id:fake:payload
    37210     89/<- %esi 4/r32/esp
    37211 $test-add-literal-to-mem:initialize-stmt:
    37212     # var stmt/esi: (addr statement)
    37213     68/push 0/imm32/next
    37214     68/push 0/imm32/next
    37215     68/push 0/imm32/outputs
    37216     68/push 0/imm32/outputs
    37217     56/push-esi/inouts
    37218     68/push 0x11/imm32/alloc-id:fake
    37219     68/push 0/imm32/operation
    37220     68/push 0/imm32/operation
    37221     68/push 1/imm32/tag:stmt1
    37222     89/<- %esi 4/r32/esp
    37223 $test-add-literal-to-mem:initialize-stmt-operation:
    37224     # stmt->operation = "add-to"
    37225     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37226     (copy-array Heap "add-to" %eax)
    37227     # convert
    37228     c7 0/subop/copy *Curr-block-depth 0/imm32
    37229     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37230     (flush _test-output-buffered-file)
    37231 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37237     # check output
    37238     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
    37239     # . epilogue
    37240     89/<- %esp 5/r32/ebp
    37241     5d/pop-to-ebp
    37242     c3/return
    37243
    37244 test-shift-reg-by-literal:
    37245     #   var1/ecx <- shift-left 2
    37246     # =>
    37247     #   c1/shift 4/subop/left %ecx 2/imm8
    37248     #
    37249     # . prologue
    37250     55/push-ebp
    37251     89/<- %ebp 4/r32/esp
    37252     # setup
    37253     (clear-stream _test-output-stream)
    37254     (clear-stream $_test-output-buffered-file->buffer)
    37255 $test-shift-reg-by-literal:initialize-var-type:
    37256     # var type/ecx: (payload type-tree) = int
    37257     68/push 0/imm32/right:null
    37258     68/push 0/imm32/right:null
    37259     68/push 0/imm32/left:unused
    37260     68/push 1/imm32/value:int
    37261     68/push 1/imm32/is-atom?:true
    37262     68/push 0x11/imm32/alloc-id:fake:payload
    37263     89/<- %ecx 4/r32/esp
    37264 $test-shift-reg-by-literal:initialize-var:
    37265     # var v/ecx: (payload var)
    37266     68/push 0/imm32/register
    37267     68/push 0/imm32/register
    37268     68/push 0/imm32/no-stack-offset
    37269     68/push 1/imm32/block-depth
    37270     51/push-ecx
    37271     68/push 0x11/imm32/alloc-id:fake
    37272     68/push 0/imm32/name
    37273     68/push 0/imm32/name
    37274     68/push 0x11/imm32/alloc-id:fake:payload
    37275     89/<- %ecx 4/r32/esp
    37276 $test-shift-reg-by-literal:initialize-var-name:
    37277     # v->name = "v"
    37278     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37279     (copy-array Heap "v" %eax)
    37280 $test-shift-reg-by-literal:initialize-var-register:
    37281     # v->register = "ecx"
    37282     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37283     (copy-array Heap "ecx" %eax)
    37284 $test-shift-reg-by-literal:initialize-literal-type:
    37285     # var type/edx: (payload type-tree) = literal
    37286     68/push 0/imm32/right:null
    37287     68/push 0/imm32/right:null
    37288     68/push 0/imm32/left:unused
    37289     68/push 0/imm32/value:literal
    37290     68/push 1/imm32/is-atom?:true
    37291     68/push 0x11/imm32/alloc-id:fake:payload
    37292     89/<- %edx 4/r32/esp
    37293 $test-shift-reg-by-literal:initialize-literal:
    37294     # var l/edx: (payload var)
    37295     68/push 0/imm32/register
    37296     68/push 0/imm32/register
    37297     68/push 0/imm32/no-stack-offset
    37298     68/push 1/imm32/block-depth
    37299     52/push-edx
    37300     68/push 0x11/imm32/alloc-id:fake
    37301     68/push 0/imm32/name
    37302     68/push 0/imm32/name
    37303     68/push 0x11/imm32/alloc-id:fake:payload
    37304     89/<- %edx 4/r32/esp
    37305 $test-shift-reg-by-literal:initialize-literal-value:
    37306     # l->name = "2"
    37307     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37308     (copy-array Heap "2" %eax)
    37309 $test-shift-reg-by-literal:initialize-inouts:
    37310     # var inouts/esi: (payload stmt-var) = [l]
    37311     68/push 0/imm32/is-deref:false
    37312     68/push 0/imm32/next
    37313     68/push 0/imm32/next
    37314     52/push-edx/l
    37315     68/push 0x11/imm32/alloc-id:fake
    37316     68/push 0x11/imm32/alloc-id:fake:payload
    37317     89/<- %esi 4/r32/esp
    37318 $test-shift-reg-by-literal:initialize-outputs:
    37319     # var outputs/edi: (payload stmt-var) = [v]
    37320     68/push 0/imm32/is-deref:false
    37321     68/push 0/imm32/next
    37322     68/push 0/imm32/next
    37323     51/push-ecx/v
    37324     68/push 0x11/imm32/alloc-id:fake
    37325     68/push 0x11/imm32/alloc-id:fake:payload
    37326     89/<- %edi 4/r32/esp
    37327 $test-shift-reg-by-literal:initialize-stmt:
    37328     # var stmt/esi: (addr statement)
    37329     68/push 0/imm32/next
    37330     68/push 0/imm32/next
    37331     57/push-edi/outputs
    37332     68/push 0x11/imm32/alloc-id:fake
    37333     56/push-esi/inouts
    37334     68/push 0x11/imm32/alloc-id:fake
    37335     68/push 0/imm32/operation
    37336     68/push 0/imm32/operation
    37337     68/push 1/imm32/tag:stmt1
    37338     89/<- %esi 4/r32/esp
    37339 $test-shift-reg-by-literal:initialize-stmt-operation:
    37340     # stmt->operation = "shift-left"
    37341     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37342     (copy-array Heap "shift-left" %eax)
    37343     # convert
    37344     c7 0/subop/copy *Curr-block-depth 0/imm32
    37345     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37346     (flush _test-output-buffered-file)
    37347 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37353     # check output
    37354     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
    37355     # . epilogue
    37356     89/<- %esp 5/r32/ebp
    37357     5d/pop-to-ebp
    37358     c3/return
    37359
    37360 test-shift-mem-by-literal:
    37361     #   shift-left var 3
    37362     # =>
    37363     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
    37364     #
    37365     # . prologue
    37366     55/push-ebp
    37367     89/<- %ebp 4/r32/esp
    37368     # setup
    37369     (clear-stream _test-output-stream)
    37370     (clear-stream $_test-output-buffered-file->buffer)
    37371 $test-shift-mem-by-literal:initialize-type:
    37372     # var type/ecx: (payload type-tree) = int
    37373     68/push 0/imm32/right:null
    37374     68/push 0/imm32/right:null
    37375     68/push 0/imm32/left:unused
    37376     68/push 1/imm32/value:int
    37377     68/push 1/imm32/is-atom?:true
    37378     68/push 0x11/imm32/alloc-id:fake:payload
    37379     89/<- %ecx 4/r32/esp
    37380 $test-shift-mem-by-literal:initialize-var1:
    37381     # var var1/ecx: (payload var)
    37382     68/push 0/imm32/register
    37383     68/push 0/imm32/register
    37384     68/push 8/imm32/stack-offset
    37385     68/push 1/imm32/block-depth
    37386     51/push-ecx
    37387     68/push 0x11/imm32/alloc-id:fake
    37388     68/push 0/imm32/name
    37389     68/push 0/imm32/name
    37390     68/push 0x11/imm32/alloc-id:fake:payload
    37391     89/<- %ecx 4/r32/esp
    37392 $test-shift-mem-by-literal:initialize-var1-name:
    37393     # var1->name = "var1"
    37394     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37395     (copy-array Heap "var1" %eax)
    37396 $test-shift-mem-by-literal:initialize-literal-type:
    37397     # var type/edx: (payload type-tree) = literal
    37398     68/push 0/imm32/right:null
    37399     68/push 0/imm32/right:null
    37400     68/push 0/imm32/left:unused
    37401     68/push 0/imm32/value:literal
    37402     68/push 1/imm32/is-atom?:true
    37403     68/push 0x11/imm32/alloc-id:fake:payload
    37404     89/<- %edx 4/r32/esp
    37405 $test-shift-mem-by-literal:initialize-literal:
    37406     # var l/edx: (payload var)
    37407     68/push 0/imm32/register
    37408     68/push 0/imm32/register
    37409     68/push 0/imm32/no-stack-offset
    37410     68/push 1/imm32/block-depth
    37411     52/push-edx
    37412     68/push 0x11/imm32/alloc-id:fake
    37413     68/push 0/imm32/name
    37414     68/push 0/imm32/name
    37415     68/push 0x11/imm32/alloc-id:fake:payload
    37416     89/<- %edx 4/r32/esp
    37417 $test-shift-mem-by-literal:initialize-literal-value:
    37418     # l->name = "3"
    37419     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37420     (copy-array Heap "3" %eax)
    37421 $test-shift-mem-by-literal:initialize-inouts:
    37422     # var inouts/esi: (payload stmt-var) = [l]
    37423     68/push 0/imm32/is-deref:false
    37424     68/push 0/imm32/next
    37425     68/push 0/imm32/next
    37426     52/push-edx/l
    37427     68/push 0x11/imm32/alloc-id:fake
    37428     68/push 0x11/imm32/alloc-id:fake:payload
    37429     89/<- %esi 4/r32/esp
    37430     # var inouts = (handle stmt-var) = [var1, var2]
    37431     68/push 0/imm32/is-deref:false
    37432     56/push-esi/next
    37433     68/push 0x11/imm32/alloc-id:fake
    37434     51/push-ecx/var1
    37435     68/push 0x11/imm32/alloc-id:fake
    37436     68/push 0x11/imm32/alloc-id:fake:payload
    37437     89/<- %esi 4/r32/esp
    37438 $test-shift-mem-by-literal:initialize-stmt:
    37439     # var stmt/esi: (addr statement)
    37440     68/push 0/imm32/next
    37441     68/push 0/imm32/next
    37442     68/push 0/imm32/outputs
    37443     68/push 0/imm32/outputs
    37444     56/push-esi/inouts
    37445     68/push 0x11/imm32/alloc-id:fake
    37446     68/push 0/imm32/operation
    37447     68/push 0/imm32/operation
    37448     68/push 1/imm32/tag:stmt1
    37449     89/<- %esi 4/r32/esp
    37450 $test-shift-mem-by-literal:initialize-stmt-operation:
    37451     # stmt->operation = "shift-left"
    37452     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37453     (copy-array Heap "shift-left" %eax)
    37454     # convert
    37455     c7 0/subop/copy *Curr-block-depth 0/imm32
    37456     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37457     (flush _test-output-buffered-file)
    37458 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37464     # check output
    37465     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
    37466     # . epilogue
    37467     89/<- %esp 5/r32/ebp
    37468     5d/pop-to-ebp
    37469     c3/return
    37470
    37471 test-compare-reg-with-reg:
    37472     #   compare var1/ecx, var2/eax
    37473     # =>
    37474     #   39/compare %ecx 0/r32/eax
    37475     #
    37476     # . prologue
    37477     55/push-ebp
    37478     89/<- %ebp 4/r32/esp
    37479     # setup
    37480     (clear-stream _test-output-stream)
    37481     (clear-stream $_test-output-buffered-file->buffer)
    37482 $test-compare-reg-with-reg:initialize-type:
    37483     # var type/ecx: (payload type-tree) = int
    37484     68/push 0/imm32/right:null
    37485     68/push 0/imm32/right:null
    37486     68/push 0/imm32/left:unused
    37487     68/push 1/imm32/value:int
    37488     68/push 1/imm32/is-atom?:true
    37489     68/push 0x11/imm32/alloc-id:fake:payload
    37490     89/<- %ecx 4/r32/esp
    37491 $test-compare-reg-with-reg:initialize-var1:
    37492     # var var1/ecx: (payload var)
    37493     68/push 0/imm32/register
    37494     68/push 0/imm32/register
    37495     68/push 0/imm32/no-stack-offset
    37496     68/push 1/imm32/block-depth
    37497     51/push-ecx
    37498     68/push 0x11/imm32/alloc-id:fake
    37499     68/push 0/imm32/name
    37500     68/push 0/imm32/name
    37501     68/push 0x11/imm32/alloc-id:fake:payload
    37502     89/<- %ecx 4/r32/esp
    37503 $test-compare-reg-with-reg:initialize-var1-name:
    37504     # var1->name = "var1"
    37505     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37506     (copy-array Heap "var1" %eax)
    37507 $test-compare-reg-with-reg:initialize-var1-register:
    37508     # var1->register = "ecx"
    37509     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37510     (copy-array Heap "ecx" %eax)
    37511 $test-compare-reg-with-reg:initialize-var2:
    37512     # var var2/edx: (payload var)
    37513     68/push 0/imm32/register
    37514     68/push 0/imm32/register
    37515     68/push 0/imm32/no-stack-offset
    37516     68/push 1/imm32/block-depth
    37517     ff 6/subop/push *(ecx+0x10)
    37518     68/push 0x11/imm32/alloc-id:fake
    37519     68/push 0/imm32/name
    37520     68/push 0/imm32/name
    37521     68/push 0x11/imm32/alloc-id:fake:payload
    37522     89/<- %edx 4/r32/esp
    37523 $test-compare-reg-with-reg:initialize-var2-name:
    37524     # var2->name = "var2"
    37525     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37526     (copy-array Heap "var2" %eax)
    37527 $test-compare-reg-with-reg:initialize-var2-register:
    37528     # var2->register = "eax"
    37529     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37530     (copy-array Heap "eax" %eax)
    37531 $test-compare-reg-with-reg:initialize-inouts:
    37532     # var inouts/esi: (payload stmt-var) = [var2]
    37533     68/push 0/imm32/is-deref:false
    37534     68/push 0/imm32/next
    37535     68/push 0/imm32/next
    37536     52/push-edx/var2
    37537     68/push 0x11/imm32/alloc-id:fake
    37538     68/push 0x11/imm32/alloc-id:fake:payload
    37539     89/<- %esi 4/r32/esp
    37540     # inouts = [var1, var2]
    37541     68/push 0/imm32/is-deref:false
    37542     56/push-esi/next
    37543     68/push 0x11/imm32/alloc-id:fake
    37544     51/push-ecx/var1
    37545     68/push 0x11/imm32/alloc-id:fake
    37546     68/push 0x11/imm32/alloc-id:fake:payload
    37547     89/<- %esi 4/r32/esp
    37548 $test-compare-reg-with-reg:initialize-stmt:
    37549     # var stmt/esi: (addr statement)
    37550     68/push 0/imm32/next
    37551     68/push 0/imm32/next
    37552     68/push 0/imm32/outputs
    37553     68/push 0/imm32/outputs
    37554     56/push-esi/inouts
    37555     68/push 0x11/imm32/alloc-id:fake
    37556     68/push 0/imm32/operation
    37557     68/push 0/imm32/operation
    37558     68/push 1/imm32/tag:stmt1
    37559     89/<- %esi 4/r32/esp
    37560 $test-compare-reg-with-reg:initialize-stmt-operation:
    37561     # stmt->operation = "compare"
    37562     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37563     (copy-array Heap "compare" %eax)
    37564     # convert
    37565     c7 0/subop/copy *Curr-block-depth 0/imm32
    37566     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37567     (flush _test-output-buffered-file)
    37568 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37574     # check output
    37575     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
    37576     # . epilogue
    37577     89/<- %esp 5/r32/ebp
    37578     5d/pop-to-ebp
    37579     c3/return
    37580
    37581 test-compare-mem-with-reg:
    37582     #   compare var1, var2/eax
    37583     # =>
    37584     #   39/compare *(ebp+___) 0/r32/eax
    37585     #
    37586     # . prologue
    37587     55/push-ebp
    37588     89/<- %ebp 4/r32/esp
    37589     # setup
    37590     (clear-stream _test-output-stream)
    37591     (clear-stream $_test-output-buffered-file->buffer)
    37592 $test-compare-mem-with-reg:initialize-type:
    37593     # var type/ecx: (payload type-tree) = int
    37594     68/push 0/imm32/right:null
    37595     68/push 0/imm32/right:null
    37596     68/push 0/imm32/left:unused
    37597     68/push 1/imm32/value:int
    37598     68/push 1/imm32/is-atom?:true
    37599     68/push 0x11/imm32/alloc-id:fake:payload
    37600     89/<- %ecx 4/r32/esp
    37601 $test-compare-mem-with-reg:initialize-var1:
    37602     # var var1/ecx: (payload var)
    37603     68/push 0/imm32/register
    37604     68/push 0/imm32/register
    37605     68/push 8/imm32/stack-offset
    37606     68/push 1/imm32/block-depth
    37607     51/push-ecx
    37608     68/push 0x11/imm32/alloc-id:fake
    37609     68/push 0/imm32/name
    37610     68/push 0/imm32/name
    37611     68/push 0x11/imm32/alloc-id:fake:payload
    37612     89/<- %ecx 4/r32/esp
    37613 $test-compare-mem-with-reg:initialize-var1-name:
    37614     # var1->name = "var1"
    37615     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37616     (copy-array Heap "var1" %eax)
    37617 $test-compare-mem-with-reg:initialize-var2:
    37618     # var var2/edx: (payload var)
    37619     68/push 0/imm32/register
    37620     68/push 0/imm32/register
    37621     68/push 0/imm32/no-stack-offset
    37622     68/push 1/imm32/block-depth
    37623     ff 6/subop/push *(ecx+0x10)
    37624     68/push 0x11/imm32/alloc-id:fake
    37625     68/push 0/imm32/name
    37626     68/push 0/imm32/name
    37627     68/push 0x11/imm32/alloc-id:fake:payload
    37628     89/<- %edx 4/r32/esp
    37629 $test-compare-mem-with-reg:initialize-var2-name:
    37630     # var2->name = "var2"
    37631     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37632     (copy-array Heap "var2" %eax)
    37633 $test-compare-mem-with-reg:initialize-var2-register:
    37634     # var2->register = "eax"
    37635     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37636     (copy-array Heap "eax" %eax)
    37637 $test-compare-mem-with-reg:initialize-inouts:
    37638     # var inouts/esi: (payload stmt-var) = [var2]
    37639     68/push 0/imm32/is-deref:false
    37640     68/push 0/imm32/next
    37641     68/push 0/imm32/next
    37642     52/push-edx/var2
    37643     68/push 0x11/imm32/alloc-id:fake
    37644     68/push 0x11/imm32/alloc-id:fake:payload
    37645     89/<- %esi 4/r32/esp
    37646     # inouts = [var1, var2]
    37647     68/push 0/imm32/is-deref:false
    37648     56/push-esi/next
    37649     68/push 0x11/imm32/alloc-id:fake
    37650     51/push-ecx/var1
    37651     68/push 0x11/imm32/alloc-id:fake
    37652     68/push 0x11/imm32/alloc-id:fake:payload
    37653     89/<- %esi 4/r32/esp
    37654 $test-compare-mem-with-reg:initialize-stmt:
    37655     # var stmt/esi: (addr statement)
    37656     68/push 0/imm32/next
    37657     68/push 0/imm32/next
    37658     68/push 0/imm32/outputs
    37659     68/push 0/imm32/outputs
    37660     56/push-esi/inouts
    37661     68/push 0x11/imm32/alloc-id:fake
    37662     68/push 0/imm32/operation
    37663     68/push 0/imm32/operation
    37664     68/push 1/imm32/tag:stmt1
    37665     89/<- %esi 4/r32/esp
    37666 $test-compare-mem-with-reg:initialize-stmt-operation:
    37667     # stmt->operation = "compare"
    37668     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37669     (copy-array Heap "compare" %eax)
    37670     # convert
    37671     c7 0/subop/copy *Curr-block-depth 0/imm32
    37672     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37673     (flush _test-output-buffered-file)
    37674 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37680     # check output
    37681     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
    37682     # . epilogue
    37683     89/<- %esp 5/r32/ebp
    37684     5d/pop-to-ebp
    37685     c3/return
    37686
    37687 test-compare-reg-with-mem:
    37688     #   compare var1/eax, var2
    37689     # =>
    37690     #   3b/compare<- *(ebp+___) 0/r32/eax
    37691     #
    37692     # . prologue
    37693     55/push-ebp
    37694     89/<- %ebp 4/r32/esp
    37695     # setup
    37696     (clear-stream _test-output-stream)
    37697     (clear-stream $_test-output-buffered-file->buffer)
    37698 $test-compare-reg-with-mem:initialize-type:
    37699     # var type/ecx: (payload type-tree) = int
    37700     68/push 0/imm32/right:null
    37701     68/push 0/imm32/right:null
    37702     68/push 0/imm32/left:unused
    37703     68/push 1/imm32/value:int
    37704     68/push 1/imm32/is-atom?:true
    37705     68/push 0x11/imm32/alloc-id:fake:payload
    37706     89/<- %ecx 4/r32/esp
    37707 $test-compare-reg-with-mem:initialize-var1:
    37708     # var var1/ecx: (payload var)
    37709     68/push 0/imm32/register
    37710     68/push 0/imm32/register
    37711     68/push 0/imm32/no-stack-offset
    37712     68/push 1/imm32/block-depth
    37713     51/push-ecx
    37714     68/push 0x11/imm32/alloc-id:fake
    37715     68/push 0/imm32/name
    37716     68/push 0/imm32/name
    37717     68/push 0x11/imm32/alloc-id:fake:payload
    37718     89/<- %ecx 4/r32/esp
    37719 $test-compare-reg-with-mem:initialize-var1-name:
    37720     # var1->name = "var1"
    37721     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37722     (copy-array Heap "var1" %eax)
    37723 $test-compare-reg-with-mem:initialize-var1-register:
    37724     # var1->register = "eax"
    37725     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37726     (copy-array Heap "eax" %eax)
    37727 $test-compare-reg-with-mem:initialize-var2:
    37728     # var var2/edx: (payload var)
    37729     68/push 0/imm32/register
    37730     68/push 0/imm32/register
    37731     68/push 8/imm32/stack-offset
    37732     68/push 1/imm32/block-depth
    37733     ff 6/subop/push *(ecx+0x10)
    37734     68/push 0x11/imm32/alloc-id:fake
    37735     68/push 0/imm32/name
    37736     68/push 0/imm32/name
    37737     68/push 0x11/imm32/alloc-id:fake:payload
    37738     89/<- %edx 4/r32/esp
    37739 $test-compare-reg-with-mem:initialize-var2-name:
    37740     # var2->name = "var2"
    37741     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37742     (copy-array Heap "var2" %eax)
    37743 $test-compare-reg-with-mem:initialize-inouts:
    37744     # var inouts/esi: (payload stmt-var) = [var2]
    37745     68/push 0/imm32/is-deref:false
    37746     68/push 0/imm32/next
    37747     68/push 0/imm32/next
    37748     52/push-edx/var2
    37749     68/push 0x11/imm32/alloc-id:fake
    37750     68/push 0x11/imm32/alloc-id:fake:payload
    37751     89/<- %esi 4/r32/esp
    37752     # inouts = [var1, var2]
    37753     68/push 0/imm32/is-deref:false
    37754     56/push-esi/next
    37755     68/push 0x11/imm32/alloc-id:fake
    37756     51/push-ecx/var1
    37757     68/push 0x11/imm32/alloc-id:fake
    37758     68/push 0x11/imm32/alloc-id:fake:payload
    37759     89/<- %esi 4/r32/esp
    37760 $test-compare-reg-with-mem:initialize-stmt:
    37761     # var stmt/esi: (addr statement)
    37762     68/push 0/imm32/next
    37763     68/push 0/imm32/next
    37764     68/push 0/imm32/outputs
    37765     68/push 0/imm32/outputs
    37766     56/push-esi/inouts
    37767     68/push 0x11/imm32/alloc-id:fake
    37768     68/push 0/imm32/operation
    37769     68/push 0/imm32/operation
    37770     68/push 1/imm32/tag:stmt1
    37771     89/<- %esi 4/r32/esp
    37772 $test-compare-reg-with-mem:initialize-stmt-operation:
    37773     # stmt->operation = "compare"
    37774     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37775     (copy-array Heap "compare" %eax)
    37776     # convert
    37777     c7 0/subop/copy *Curr-block-depth 0/imm32
    37778     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37779     (flush _test-output-buffered-file)
    37780 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37786     # check output
    37787     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
    37788     # . epilogue
    37789     89/<- %esp 5/r32/ebp
    37790     5d/pop-to-ebp
    37791     c3/return
    37792
    37793 test-compare-mem-with-literal:
    37794     #   compare var1, 0x34
    37795     # =>
    37796     #   81 7/subop/compare *(ebp+___) 0x34/imm32
    37797     #
    37798     # . prologue
    37799     55/push-ebp
    37800     89/<- %ebp 4/r32/esp
    37801     # setup
    37802     (clear-stream _test-output-stream)
    37803     (clear-stream $_test-output-buffered-file->buffer)
    37804 $test-compare-mem-with-literal:initialize-type:
    37805     # var type/ecx: (payload type-tree) = int
    37806     68/push 0/imm32/right:null
    37807     68/push 0/imm32/right:null
    37808     68/push 0/imm32/left:unused
    37809     68/push 1/imm32/value:int
    37810     68/push 1/imm32/is-atom?:true
    37811     68/push 0x11/imm32/alloc-id:fake:payload
    37812     89/<- %ecx 4/r32/esp
    37813 $test-compare-mem-with-literal:initialize-var1:
    37814     # var var1/ecx: (payload var)
    37815     68/push 0/imm32/register
    37816     68/push 0/imm32/register
    37817     68/push 8/imm32/stack-offset
    37818     68/push 1/imm32/block-depth
    37819     51/push-ecx
    37820     68/push 0x11/imm32/alloc-id:fake
    37821     68/push 0/imm32/name
    37822     68/push 0/imm32/name
    37823     68/push 0x11/imm32/alloc-id:fake:payload
    37824     89/<- %ecx 4/r32/esp
    37825 $test-compare-mem-with-literal:initialize-var1-name:
    37826     # var1->name = "var1"
    37827     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37828     (copy-array Heap "var1" %eax)
    37829 $test-compare-mem-with-literal:initialize-literal-type:
    37830     # var type/edx: (payload type-tree) = literal
    37831     68/push 0/imm32/right:null
    37832     68/push 0/imm32/right:null
    37833     68/push 0/imm32/left:unused
    37834     68/push 0/imm32/value:literal
    37835     68/push 1/imm32/is-atom?:true
    37836     68/push 0x11/imm32/alloc-id:fake:payload
    37837     89/<- %edx 4/r32/esp
    37838 $test-compare-mem-with-literal:initialize-literal:
    37839     # var l/edx: (payload var)
    37840     68/push 0/imm32/register
    37841     68/push 0/imm32/register
    37842     68/push 0/imm32/no-stack-offset
    37843     68/push 1/imm32/block-depth
    37844     52/push-edx
    37845     68/push 0x11/imm32/alloc-id:fake
    37846     68/push 0/imm32/name
    37847     68/push 0/imm32/name
    37848     68/push 0x11/imm32/alloc-id:fake:payload
    37849     89/<- %edx 4/r32/esp
    37850 $test-compare-mem-with-literal:initialize-literal-value:
    37851     # l->name = "0x34"
    37852     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37853     (copy-array Heap "0x34" %eax)
    37854 $test-compare-mem-with-literal:initialize-inouts:
    37855     # var inouts/esi: (payload stmt-var) = [l]
    37856     68/push 0/imm32/is-deref:false
    37857     68/push 0/imm32/next
    37858     68/push 0/imm32/next
    37859     52/push-edx/l
    37860     68/push 0x11/imm32/alloc-id:fake
    37861     68/push 0x11/imm32/alloc-id:fake:payload
    37862     89/<- %esi 4/r32/esp
    37863     # var inouts = (handle stmt-var) = [var1, var2]
    37864     68/push 0/imm32/is-deref:false
    37865     56/push-esi/next
    37866     68/push 0x11/imm32/alloc-id:fake
    37867     51/push-ecx/var1
    37868     68/push 0x11/imm32/alloc-id:fake
    37869     68/push 0x11/imm32/alloc-id:fake:payload
    37870     89/<- %esi 4/r32/esp
    37871 $test-compare-mem-with-literal:initialize-stmt:
    37872     # var stmt/esi: (addr statement)
    37873     68/push 0/imm32/next
    37874     68/push 0/imm32/next
    37875     68/push 0/imm32/outputs
    37876     68/push 0/imm32/outputs
    37877     56/push-esi/inouts
    37878     68/push 0x11/imm32/alloc-id:fake
    37879     68/push 0/imm32/operation
    37880     68/push 0/imm32/operation
    37881     68/push 1/imm32/tag:stmt1
    37882     89/<- %esi 4/r32/esp
    37883 $test-compare-mem-with-literal:initialize-stmt-operation:
    37884     # stmt->operation = "compare"
    37885     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37886     (copy-array Heap "compare" %eax)
    37887     # convert
    37888     c7 0/subop/copy *Curr-block-depth 0/imm32
    37889     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37890     (flush _test-output-buffered-file)
    37891 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37897     # check output
    37898     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
    37899     # . epilogue
    37900     89/<- %esp 5/r32/ebp
    37901     5d/pop-to-ebp
    37902     c3/return
    37903
    37904 test-compare-eax-with-literal:
    37905     #   compare var1/eax 0x34
    37906     # =>
    37907     #   3d/compare-eax-with 0x34/imm32
    37908     #
    37909     # . prologue
    37910     55/push-ebp
    37911     89/<- %ebp 4/r32/esp
    37912     # setup
    37913     (clear-stream _test-output-stream)
    37914     (clear-stream $_test-output-buffered-file->buffer)
    37915 $test-compare-eax-with-literal:initialize-type:
    37916     # var type/ecx: (payload type-tree) = int
    37917     68/push 0/imm32/right:null
    37918     68/push 0/imm32/right:null
    37919     68/push 0/imm32/left:unused
    37920     68/push 1/imm32/value:int
    37921     68/push 1/imm32/is-atom?:true
    37922     68/push 0x11/imm32/alloc-id:fake:payload
    37923     89/<- %ecx 4/r32/esp
    37924 $test-compare-eax-with-literal:initialize-var1:
    37925     # var var1/ecx: (payload var)
    37926     68/push 0/imm32/register
    37927     68/push 0/imm32/register
    37928     68/push 0/imm32/no-stack-offset
    37929     68/push 1/imm32/block-depth
    37930     51/push-ecx
    37931     68/push 0x11/imm32/alloc-id:fake
    37932     68/push 0/imm32/name
    37933     68/push 0/imm32/name
    37934     68/push 0x11/imm32/alloc-id:fake:payload
    37935     89/<- %ecx 4/r32/esp
    37936 $test-compare-eax-with-literal:initialize-var1-name:
    37937     # var1->name = "var1"
    37938     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37939     (copy-array Heap "var1" %eax)
    37940 $test-compare-eax-with-literal:initialize-var1-register:
    37941     # v->register = "eax"
    37942     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37943     (copy-array Heap "eax" %eax)
    37944 $test-compare-eax-with-literal:initialize-literal-type:
    37945     # var type/edx: (payload type-tree) = literal
    37946     68/push 0/imm32/right:null
    37947     68/push 0/imm32/right:null
    37948     68/push 0/imm32/left:unused
    37949     68/push 0/imm32/value:literal
    37950     68/push 1/imm32/is-atom?:true
    37951     68/push 0x11/imm32/alloc-id:fake:payload
    37952     89/<- %edx 4/r32/esp
    37953 $test-compare-eax-with-literal:initialize-literal:
    37954     # var l/edx: (payload var)
    37955     68/push 0/imm32/register
    37956     68/push 0/imm32/register
    37957     68/push 0/imm32/no-stack-offset
    37958     68/push 1/imm32/block-depth
    37959     52/push-edx
    37960     68/push 0x11/imm32/alloc-id:fake
    37961     68/push 0/imm32/name
    37962     68/push 0/imm32/name
    37963     68/push 0x11/imm32/alloc-id:fake:payload
    37964     89/<- %edx 4/r32/esp
    37965 $test-compare-eax-with-literal:initialize-literal-value:
    37966     # l->name = "0x34"
    37967     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37968     (copy-array Heap "0x34" %eax)
    37969 $test-compare-eax-with-literal:initialize-inouts:
    37970     # var inouts/esi: (payload stmt-var) = [l]
    37971     68/push 0/imm32/is-deref:false
    37972     68/push 0/imm32/next
    37973     68/push 0/imm32/next
    37974     52/push-edx/l
    37975     68/push 0x11/imm32/alloc-id:fake
    37976     68/push 0x11/imm32/alloc-id:fake:payload
    37977     89/<- %esi 4/r32/esp
    37978     # var inouts = (handle stmt-var) = [var1, var2]
    37979     68/push 0/imm32/is-deref:false
    37980     56/push-esi/next
    37981     68/push 0x11/imm32/alloc-id:fake
    37982     51/push-ecx/var1
    37983     68/push 0x11/imm32/alloc-id:fake
    37984     68/push 0x11/imm32/alloc-id:fake:payload
    37985     89/<- %esi 4/r32/esp
    37986 $test-compare-eax-with-literal:initialize-stmt:
    37987     # var stmt/esi: (addr statement)
    37988     68/push 0/imm32/next
    37989     68/push 0/imm32/next
    37990     68/push 0/imm32/outputs
    37991     68/push 0/imm32/outputs
    37992     56/push-esi/inouts
    37993     68/push 0x11/imm32/alloc-id:fake
    37994     68/push 0/imm32/operation
    37995     68/push 0/imm32/operation
    37996     68/push 1/imm32/tag:stmt1
    37997     89/<- %esi 4/r32/esp
    37998 $test-compare-eax-with-literal:initialize-stmt-operation:
    37999     # stmt->operation = "compare"
    38000     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38001     (copy-array Heap "compare" %eax)
    38002     # convert
    38003     c7 0/subop/copy *Curr-block-depth 0/imm32
    38004     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38005     (flush _test-output-buffered-file)
    38006 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38012     # check output
    38013     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
    38014     # . epilogue
    38015     89/<- %esp 5/r32/ebp
    38016     5d/pop-to-ebp
    38017     c3/return
    38018
    38019 test-compare-reg-with-literal:
    38020     #   compare var1/ecx 0x34
    38021     # =>
    38022     #   81 7/subop/compare %ecx 0x34/imm32
    38023     #
    38024     # . prologue
    38025     55/push-ebp
    38026     89/<- %ebp 4/r32/esp
    38027     # setup
    38028     (clear-stream _test-output-stream)
    38029     (clear-stream $_test-output-buffered-file->buffer)
    38030 $test-compare-reg-with-literal:initialize-type:
    38031     # var type/ecx: (payload type-tree) = int
    38032     68/push 0/imm32/right:null
    38033     68/push 0/imm32/right:null
    38034     68/push 0/imm32/left:unused
    38035     68/push 1/imm32/value:int
    38036     68/push 1/imm32/is-atom?:true
    38037     68/push 0x11/imm32/alloc-id:fake:payload
    38038     89/<- %ecx 4/r32/esp
    38039 $test-compare-reg-with-literal:initialize-var1:
    38040     # var var1/ecx: (payload var)
    38041     68/push 0/imm32/register
    38042     68/push 0/imm32/register
    38043     68/push 0/imm32/no-stack-offset
    38044     68/push 1/imm32/block-depth
    38045     51/push-ecx
    38046     68/push 0x11/imm32/alloc-id:fake
    38047     68/push 0/imm32/name
    38048     68/push 0/imm32/name
    38049     68/push 0x11/imm32/alloc-id:fake:payload
    38050     89/<- %ecx 4/r32/esp
    38051 $test-compare-reg-with-literal:initialize-var1-name:
    38052     # var1->name = "var1"
    38053     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38054     (copy-array Heap "var1" %eax)
    38055 $test-compare-reg-with-literal:initialize-var1-register:
    38056     # v->register = "ecx"
    38057     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38058     (copy-array Heap "ecx" %eax)
    38059 $test-compare-reg-with-literal:initialize-literal-type:
    38060     # var type/edx: (payload type-tree) = literal
    38061     68/push 0/imm32/right:null
    38062     68/push 0/imm32/right:null
    38063     68/push 0/imm32/left:unused
    38064     68/push 0/imm32/value:literal
    38065     68/push 1/imm32/is-atom?:true
    38066     68/push 0x11/imm32/alloc-id:fake:payload
    38067     89/<- %edx 4/r32/esp
    38068 $test-compare-reg-with-literal:initialize-literal:
    38069     # var l/edx: (payload var)
    38070     68/push 0/imm32/register
    38071     68/push 0/imm32/register
    38072     68/push 0/imm32/no-stack-offset
    38073     68/push 1/imm32/block-depth
    38074     52/push-edx
    38075     68/push 0x11/imm32/alloc-id:fake
    38076     68/push 0/imm32/name
    38077     68/push 0/imm32/name
    38078     68/push 0x11/imm32/alloc-id:fake:payload
    38079     89/<- %edx 4/r32/esp
    38080 $test-compare-reg-with-literal:initialize-literal-value:
    38081     # l->name = "0x34"
    38082     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38083     (copy-array Heap "0x34" %eax)
    38084 $test-compare-reg-with-literal:initialize-inouts:
    38085     # var inouts/esi: (payload stmt-var) = [l]
    38086     68/push 0/imm32/is-deref:false
    38087     68/push 0/imm32/next
    38088     68/push 0/imm32/next
    38089     52/push-edx/l
    38090     68/push 0x11/imm32/alloc-id:fake
    38091     68/push 0x11/imm32/alloc-id:fake:payload
    38092     89/<- %esi 4/r32/esp
    38093     # var inouts = (handle stmt-var) = [var1, var2]
    38094     68/push 0/imm32/is-deref:false
    38095     56/push-esi/next
    38096     68/push 0x11/imm32/alloc-id:fake
    38097     51/push-ecx/var1
    38098     68/push 0x11/imm32/alloc-id:fake
    38099     68/push 0x11/imm32/alloc-id:fake:payload
    38100     89/<- %esi 4/r32/esp
    38101 $test-compare-reg-with-literal:initialize-stmt:
    38102     # var stmt/esi: (addr statement)
    38103     68/push 0/imm32/next
    38104     68/push 0/imm32/next
    38105     68/push 0/imm32/outputs
    38106     68/push 0/imm32/outputs
    38107     56/push-esi/inouts
    38108     68/push 0x11/imm32/alloc-id:fake
    38109     68/push 0/imm32/operation
    38110     68/push 0/imm32/operation
    38111     68/push 1/imm32/tag:stmt1
    38112     89/<- %esi 4/r32/esp
    38113 $test-compare-reg-with-literal:initialize-stmt-operation:
    38114     # stmt->operation = "compare"
    38115     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38116     (copy-array Heap "compare" %eax)
    38117     # convert
    38118     c7 0/subop/copy *Curr-block-depth 0/imm32
    38119     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38120     (flush _test-output-buffered-file)
    38121 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38127     # check output
    38128     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
    38129     # . epilogue
    38130     89/<- %esp 5/r32/ebp
    38131     5d/pop-to-ebp
    38132     c3/return
    38133
    38134 test-emit-subx-stmt-function-call:
    38135     # Call a function on a variable on the stack.
    38136     #   f foo
    38137     # =>
    38138     #   (f *(ebp-8))
    38139     # (Changing the function name supports overloading in general, but here it
    38140     # just serves to help disambiguate things.)
    38141     #
    38142     # There's a variable on the var stack as follows:
    38143     #   name: 'foo'
    38144     #   type: int
    38145     #   stack-offset: -8
    38146     #
    38147     # There's nothing in primitives.
    38148     #
    38149     # We don't perform any checking here on the type of 'f'.
    38150     #
    38151     # . prologue
    38152     55/push-ebp
    38153     89/<- %ebp 4/r32/esp
    38154     # setup
    38155     (clear-stream _test-output-stream)
    38156     (clear-stream $_test-output-buffered-file->buffer)
    38157 $test-emit-subx-function-call:initialize-type:
    38158     # var type/ecx: (payload type-tree) = int
    38159     68/push 0/imm32/right:null
    38160     68/push 0/imm32/right:null
    38161     68/push 0/imm32/left:unused
    38162     68/push 1/imm32/value:int
    38163     68/push 1/imm32/is-atom?:true
    38164     68/push 0x11/imm32/alloc-id:fake:payload
    38165     89/<- %ecx 4/r32/esp
    38166 $test-emit-subx-function-call:initialize-var:
    38167     # var var-foo/ecx: (payload var) = var(type)
    38168     68/push 0/imm32/no-register
    38169     68/push 0/imm32/no-register
    38170     68/push -8/imm32/stack-offset
    38171     68/push 1/imm32/block-depth
    38172     51/push-ecx/type
    38173     68/push 0x11/imm32/alloc-id:fake
    38174     68/push 0/imm32/name
    38175     68/push 0/imm32/name
    38176     68/push 0x11/imm32/alloc-id:fake:payload
    38177     89/<- %ecx 4/r32/esp
    38178 $test-emit-subx-function-call:initialize-var-name:
    38179     # var-foo->name = "foo"
    38180     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38181     (copy-array Heap "foo" %eax)
    38182 $test-emit-subx-function-call:initialize-stmt-var:
    38183     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38184     68/push 0/imm32/is-deref:false
    38185     68/push 0/imm32/next
    38186     68/push 0/imm32/next
    38187     51/push-ecx/var-foo
    38188     68/push 0x11/imm32/alloc-id:fake
    38189     68/push 0x11/imm32/alloc-id:fake:payload
    38190     89/<- %ebx 4/r32/esp
    38191 $test-emit-subx-function-call:initialize-stmt:
    38192     # var stmt/esi: (addr statement)
    38193     68/push 0/imm32/no-outputs
    38194     68/push 0/imm32/no-outputs
    38195     53/push-ebx/inouts
    38196     68/push 0x11/imm32/alloc-id:fake
    38197     68/push 0/imm32/operation
    38198     68/push 0/imm32/operation
    38199     68/push 1/imm32/tag
    38200     89/<- %esi 4/r32/esp
    38201 $test-emit-subx-function-call:initialize-stmt-operation:
    38202     # stmt->operation = "f"
    38203     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38204     (copy-array Heap "f" %eax)
    38205     # convert
    38206     c7 0/subop/copy *Curr-block-depth 0/imm32
    38207     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
    38208     (flush _test-output-buffered-file)
    38209 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38215     # check output
    38216     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
    38217     # . epilogue
    38218     89/<- %esp 5/r32/ebp
    38219     5d/pop-to-ebp
    38220     c3/return
    38221
    38222 test-emit-subx-stmt-function-call-with-literal-arg:
    38223     # Call a function on a literal.
    38224     #   f 0x34
    38225     # =>
    38226     #   (f2 0x34)
    38227     #
    38228     # . prologue
    38229     55/push-ebp
    38230     89/<- %ebp 4/r32/esp
    38231     # setup
    38232     (clear-stream _test-output-stream)
    38233     (clear-stream $_test-output-buffered-file->buffer)
    38234 $test-emit-subx-function-call-with-literal-arg:initialize-type:
    38235     # var type/ecx: (payload type-tree) = int
    38236     68/push 0/imm32/right:null
    38237     68/push 0/imm32/right:null
    38238     68/push 0/imm32/left:unused
    38239     68/push 0/imm32/value:literal
    38240     68/push 1/imm32/is-atom?:true
    38241     68/push 0x11/imm32/alloc-id:fake:payload
    38242     89/<- %ecx 4/r32/esp
    38243 $test-emit-subx-function-call-with-literal-arg:initialize-var:
    38244     # var var-foo/ecx: (payload var) = var(lit)
    38245     68/push 0/imm32/no-register
    38246     68/push 0/imm32/no-register
    38247     68/push 0/imm32/no-stack-offset
    38248     68/push 1/imm32/block-depth
    38249     51/push-ecx/type
    38250     68/push 0x11/imm32/alloc-id:fake
    38251     68/push 0/imm32/name
    38252     68/push 0/imm32/name
    38253     68/push 0x11/imm32/alloc-id:fake:payload
    38254     89/<- %ecx 4/r32/esp
    38255 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
    38256     # var-foo->name = "0x34"
    38257     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38258     (copy-array Heap "0x34" %eax)
    38259 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
    38260     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38261     68/push 0/imm32/is-deref:false
    38262     68/push 0/imm32/next
    38263     68/push 0/imm32/next
    38264     51/push-ecx/var-foo
    38265     68/push 0x11/imm32/alloc-id:fake
    38266     68/push 0x11/imm32/alloc-id:fake:payload
    38267     89/<- %ebx 4/r32/esp
    38268 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
    38269     # var stmt/esi: (addr statement)
    38270     68/push 0/imm32/no-outputs
    38271     68/push 0/imm32/no-outputs
    38272     53/push-ebx/inouts
    38273     68/push 0x11/imm32/alloc-id:fake
    38274     68/push 0/imm32/operation
    38275     68/push 0/imm32/operation
    38276     68/push 1/imm32/tag
    38277     89/<- %esi 4/r32/esp
    38278 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
    38279     # stmt->operation = "f"
    38280     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38281     (copy-array Heap "f" %eax)
    38282     # convert
    38283     c7 0/subop/copy *Curr-block-depth 0/imm32
    38284     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
    38285     (flush _test-output-buffered-file)
    38286 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38292     # check output
    38293     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
    38294     # . epilogue
    38295     89/<- %esp 5/r32/ebp
    38296     5d/pop-to-ebp
    38297     c3/return
    38298
    38299 emit-indent:  # out: (addr buffered-file), n: int
    38300     # . prologue
    38301     55/push-ebp
    38302     89/<- %ebp 4/r32/esp
    38303     # . save registers
    38304     50/push-eax
    38305     # var i/eax: int = n
    38306     8b/-> *(ebp+0xc) 0/r32/eax
    38307     {
    38308       # if (i <= 0) break
    38309       3d/compare-eax-with 0/imm32
    38310       7e/jump-if-<= break/disp8
    38311       (write-buffered *(ebp+8) "  ")
    38312       48/decrement-eax
    38313       eb/jump loop/disp8
    38314     }
    38315 $emit-indent:end:
    38316     # . restore registers
    38317     58/pop-to-eax
    38318     # . epilogue
    38319     89/<- %esp 5/r32/ebp
    38320     5d/pop-to-ebp
    38321     c3/return
    38322
    38323 emit-subx-prologue:  # out: (addr buffered-file)
    38324     # . prologue
    38325     55/push-ebp
    38326     89/<- %ebp 4/r32/esp
    38327     #
    38328     (write-buffered *(ebp+8) "  # . prologue\n")
    38329     (write-buffered *(ebp+8) "  55/push-ebp\n")
    38330     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
    38331 $emit-subx-prologue:end:
    38332     # . epilogue
    38333     89/<- %esp 5/r32/ebp
    38334     5d/pop-to-ebp
    38335     c3/return
    38336
    38337 emit-subx-epilogue:  # out: (addr buffered-file)
    38338     # . prologue
    38339     55/push-ebp
    38340     89/<- %ebp 4/r32/esp
    38341     #
    38342     (write-buffered *(ebp+8) "  # . epilogue\n")
    38343     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
    38344     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
    38345     (write-buffered *(ebp+8) "  c3/return\n")
    38346 $emit-subx-epilogue:end:
    38347     # . epilogue
    38348     89/<- %esp 5/r32/ebp
    38349     5d/pop-to-ebp
    38350     c3/return