https://github.com/akkartik/mu/blob/main/linux/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484 #?     (test-address-with-right-type-for-stream)
  485     # if (argv[1] == "test') run-tests()
  486     {
  487       # if (argc <= 1) break
  488       81 7/subop/compare *ebp 1/imm32
  489       7e/jump-if-<= break/disp8
  490       # if (argv[1] != "test") break
  491       (kernel-string-equal? *(ebp+8) "test")  # => eax
  492       3d/compare-eax-and 0/imm32/false
  493       74/jump-if-= break/disp8
  494       #
  495       (run-tests)
  496       # syscall(exit, *Num-test-failures)
  497       8b/-> *Num-test-failures 3/r32/ebx
  498       eb/jump $mu-main:end/disp8
  499     }
  500     # otherwise convert Stdin
  501     (write-buffered Stdout "== code\n")
  502     (convert-mu Stdin Stdout Stderr 0)
  503     (flush Stdout)
  504     # syscall(exit, 0)
  505     bb/copy-to-ebx 0/imm32
  506 $mu-main:end:
  507     e8/call syscall_exit/disp32
  508 
  509 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  510     # . prologue
  511     55/push-ebp
  512     89/<- %ebp 4/r32/esp
  513     # . save registers
  514     50/push-eax
  515     # initialize global data structures
  516     c7 0/subop/copy *Next-block-index 1/imm32
  517     8b/-> *Primitive-type-ids 0/r32/eax
  518     89/<- *Type-id 0/r32/eax  # stream-write
  519     c7 0/subop/copy *_Program-functions 0/imm32
  520     c7 0/subop/copy *_Program-functions->payload 0/imm32
  521     c7 0/subop/copy *_Program-types 0/imm32
  522     c7 0/subop/copy *_Program-types->payload 0/imm32
  523     c7 0/subop/copy *_Program-signatures 0/imm32
  524     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  525     #
  526     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  527     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  528 #?     (dump-typeinfos "=== typeinfos\n")
  529     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  530     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  531 $convert-mu:end:
  532     # . restore registers
  533     58/pop-to-eax
  534     # . epilogue
  535     89/<- %esp 5/r32/ebp
  536     5d/pop-to-ebp
  537     c3/return
  538 
  539 test-convert-empty-input:
  540     # empty input => empty output
  541     # . prologue
  542     55/push-ebp
  543     89/<- %ebp 4/r32/esp
  544     # setup
  545     (clear-stream _test-input-stream)
  546     (clear-stream $_test-input-buffered-file->buffer)
  547     (clear-stream _test-output-stream)
  548     (clear-stream $_test-output-buffered-file->buffer)
  549     #
  550     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  551     (flush _test-output-buffered-file)
  552     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  553     # . epilogue
  554     89/<- %esp 5/r32/ebp
  555     5d/pop-to-ebp
  556     c3/return
  557 
  558 test-convert-function-skeleton:
  559     # . prologue
  560     55/push-ebp
  561     89/<- %ebp 4/r32/esp
  562     # setup
  563     (clear-stream _test-input-stream)
  564     (clear-stream $_test-input-buffered-file->buffer)
  565     (clear-stream _test-output-stream)
  566     (clear-stream $_test-output-buffered-file->buffer)
  567     #
  568     (write _test-input-stream "fn foo {\n")
  569     (write _test-input-stream "}\n")
  570     # convert
  571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  572     (flush _test-output-buffered-file)
  573 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  579     # check output
  580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  584     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  585     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  586     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  587     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  588     # . epilogue
  589     89/<- %esp 5/r32/ebp
  590     5d/pop-to-ebp
  591     c3/return
  592 
  593 test-convert-multiple-function-skeletons:
  594     # . prologue
  595     55/push-ebp
  596     89/<- %ebp 4/r32/esp
  597     # setup
  598     (clear-stream _test-input-stream)
  599     (clear-stream $_test-input-buffered-file->buffer)
  600     (clear-stream _test-output-stream)
  601     (clear-stream $_test-output-buffered-file->buffer)
  602     #
  603     (write _test-input-stream "fn foo {\n")
  604     (write _test-input-stream "}\n")
  605     (write _test-input-stream "fn bar {\n")
  606     (write _test-input-stream "}\n")
  607     # convert
  608     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  609     (flush _test-output-buffered-file)
  610 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  616     # check first function
  617     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  618     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  619     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  625     # check second function
  626     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  627     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  628     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  630     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  631     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  632     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  633     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  634     # . epilogue
  635     89/<- %esp 5/r32/ebp
  636     5d/pop-to-ebp
  637     c3/return
  638 
  639 test-convert-function-with-arg:
  640     # . prologue
  641     55/push-ebp
  642     89/<- %ebp 4/r32/esp
  643     # setup
  644     (clear-stream _test-input-stream)
  645     (clear-stream $_test-input-buffered-file->buffer)
  646     (clear-stream _test-output-stream)
  647     (clear-stream $_test-output-buffered-file->buffer)
  648     #
  649     (write _test-input-stream "fn foo n: int {\n")
  650     (write _test-input-stream "}\n")
  651     # convert
  652     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  653     (flush _test-output-buffered-file)
  654 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  660     # check output
  661     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  662     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  663     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  665     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  666     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  667     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  668     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  669     # . epilogue
  670     89/<- %esp 5/r32/ebp
  671     5d/pop-to-ebp
  672     c3/return
  673 
  674 test-function-with-redefined-name:
  675     # . prologue
  676     55/push-ebp
  677     89/<- %ebp 4/r32/esp
  678     # setup
  679     (clear-stream _test-input-stream)
  680     (clear-stream $_test-input-buffered-file->buffer)
  681     (clear-stream _test-output-stream)
  682     (clear-stream $_test-output-buffered-file->buffer)
  683     (clear-stream _test-error-stream)
  684     (clear-stream $_test-error-buffered-file->buffer)
  685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  686     68/push 0/imm32
  687     68/push 0/imm32
  688     89/<- %edx 4/r32/esp
  689     (tailor-exit-descriptor %edx 0x10)
  690     #
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     (write _test-input-stream "fn foo {\n")
  694     (write _test-input-stream "}\n")
  695     # convert
  696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  697     # registers except esp clobbered at this point
  698     # restore ed
  699     89/<- %edx 4/r32/esp
  700     (flush _test-output-buffered-file)
  701     (flush _test-error-buffered-file)
  702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  708     # check output
  709     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  710     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  711     # check that stop(1) was called
  712     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  713     # don't restore from ebp
  714     81 0/subop/add %esp 8/imm32
  715     # . epilogue
  716     5d/pop-to-ebp
  717     c3/return
  718 
  719 test-function-with-redefined-name-2:
  720     # . prologue
  721     55/push-ebp
  722     89/<- %ebp 4/r32/esp
  723     # setup
  724     (clear-stream _test-input-stream)
  725     (clear-stream $_test-input-buffered-file->buffer)
  726     (clear-stream _test-output-stream)
  727     (clear-stream $_test-output-buffered-file->buffer)
  728     (clear-stream _test-error-stream)
  729     (clear-stream $_test-error-buffered-file->buffer)
  730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  731     68/push 0/imm32
  732     68/push 0/imm32
  733     89/<- %edx 4/r32/esp
  734     (tailor-exit-descriptor %edx 0x10)
  735     #
  736     (write _test-input-stream "fn foo {\n")
  737     (write _test-input-stream "}\n")
  738     (write _test-input-stream "sig foo\n")
  739     # convert
  740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  741     # registers except esp clobbered at this point
  742     # restore ed
  743     89/<- %edx 4/r32/esp
  744     (flush _test-output-buffered-file)
  745     (flush _test-error-buffered-file)
  746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  752     # check output
  753     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  754     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  755     # check that stop(1) was called
  756     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  757     # don't restore from ebp
  758     81 0/subop/add %esp 8/imm32
  759     # . epilogue
  760     5d/pop-to-ebp
  761     c3/return
  762 
  763 test-function-with-redefined-name-3:
  764     # . prologue
  765     55/push-ebp
  766     89/<- %ebp 4/r32/esp
  767     # setup
  768     (clear-stream _test-input-stream)
  769     (clear-stream $_test-input-buffered-file->buffer)
  770     (clear-stream _test-output-stream)
  771     (clear-stream $_test-output-buffered-file->buffer)
  772     (clear-stream _test-error-stream)
  773     (clear-stream $_test-error-buffered-file->buffer)
  774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  775     68/push 0/imm32
  776     68/push 0/imm32
  777     89/<- %edx 4/r32/esp
  778     (tailor-exit-descriptor %edx 0x10)
  779     #
  780     (write _test-input-stream "sig foo\n")
  781     (write _test-input-stream "fn foo {\n")
  782     (write _test-input-stream "}\n")
  783     # convert
  784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  785     # registers except esp clobbered at this point
  786     # restore ed
  787     89/<- %edx 4/r32/esp
  788     (flush _test-output-buffered-file)
  789     (flush _test-error-buffered-file)
  790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  796     # check output
  797     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  798     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  799     # check that stop(1) was called
  800     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  801     # don't restore from ebp
  802     81 0/subop/add %esp 8/imm32
  803     # . epilogue
  804     5d/pop-to-ebp
  805     c3/return
  806 
  807 test-function-with-inout-in-register:
  808     # . prologue
  809     55/push-ebp
  810     89/<- %ebp 4/r32/esp
  811     # setup
  812     (clear-stream _test-input-stream)
  813     (clear-stream $_test-input-buffered-file->buffer)
  814     (clear-stream _test-output-stream)
  815     (clear-stream $_test-output-buffered-file->buffer)
  816     (clear-stream _test-error-stream)
  817     (clear-stream $_test-error-buffered-file->buffer)
  818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  819     68/push 0/imm32
  820     68/push 0/imm32
  821     89/<- %edx 4/r32/esp
  822     (tailor-exit-descriptor %edx 0x10)
  823     #
  824     (write _test-input-stream "fn foo x/eax: int {\n")
  825     (write _test-input-stream "}\n")
  826     # convert
  827     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  828     # registers except esp clobbered at this point
  829     # restore ed
  830     89/<- %edx 4/r32/esp
  831     (flush _test-output-buffered-file)
  832     (flush _test-error-buffered-file)
  833 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  839     # check output
  840     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  841     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  842     # check that stop(1) was called
  843     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  844     # don't restore from ebp
  845     81 0/subop/add %esp 8/imm32
  846     # . epilogue
  847     5d/pop-to-ebp
  848     c3/return
  849 
  850 test-function-with-addr-output:
  851     # . prologue
  852     55/push-ebp
  853     89/<- %ebp 4/r32/esp
  854     # setup
  855     (clear-stream _test-input-stream)
  856     (clear-stream $_test-input-buffered-file->buffer)
  857     (clear-stream _test-output-stream)
  858     (clear-stream $_test-output-buffered-file->buffer)
  859     (clear-stream _test-error-stream)
  860     (clear-stream $_test-error-buffered-file->buffer)
  861     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  862     68/push 0/imm32
  863     68/push 0/imm32
  864     89/<- %edx 4/r32/esp
  865     (tailor-exit-descriptor %edx 0x10)
  866     #
  867     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  868     (write _test-input-stream "}\n")
  869     # convert
  870     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  871     # registers except esp clobbered at this point
  872     # restore ed
  873     89/<- %edx 4/r32/esp
  874     (flush _test-output-buffered-file)
  875     (flush _test-error-buffered-file)
  876 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  882     # check output
  883     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  884     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  885     # check that stop(1) was called
  886     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  887     # don't restore from ebp
  888     81 0/subop/add %esp 8/imm32
  889     # . epilogue
  890     5d/pop-to-ebp
  891     c3/return
  892 
  893 test-function-with-addr-inout:
  894     # . prologue
  895     55/push-ebp
  896     89/<- %ebp 4/r32/esp
  897     # setup
  898     (clear-stream _test-input-stream)
  899     (clear-stream $_test-input-buffered-file->buffer)
  900     (clear-stream _test-output-stream)
  901     (clear-stream $_test-output-buffered-file->buffer)
  902     (clear-stream _test-error-stream)
  903     (clear-stream $_test-error-buffered-file->buffer)
  904     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  905     68/push 0/imm32
  906     68/push 0/imm32
  907     89/<- %edx 4/r32/esp
  908     (tailor-exit-descriptor %edx 0x10)
  909     #
  910     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  911     (write _test-input-stream "}\n")
  912     # convert
  913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  914     # registers except esp clobbered at this point
  915     # restore ed
  916     89/<- %edx 4/r32/esp
  917     (flush _test-output-buffered-file)
  918     (flush _test-error-buffered-file)
  919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  925     # check output
  926     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  927     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  928     # check that stop(1) was called
  929     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  930     # don't restore from ebp
  931     81 0/subop/add %esp 8/imm32
  932     # . epilogue
  933     5d/pop-to-ebp
  934     c3/return
  935 
  936 test-function-with-addr-inout-2:
  937     # . prologue
  938     55/push-ebp
  939     89/<- %ebp 4/r32/esp
  940     # setup
  941     (clear-stream _test-input-stream)
  942     (clear-stream $_test-input-buffered-file->buffer)
  943     (clear-stream _test-output-stream)
  944     (clear-stream $_test-output-buffered-file->buffer)
  945     (clear-stream _test-error-stream)
  946     (clear-stream $_test-error-buffered-file->buffer)
  947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  948     68/push 0/imm32
  949     68/push 0/imm32
  950     89/<- %edx 4/r32/esp
  951     (tailor-exit-descriptor %edx 0x10)
  952     #
  953     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  954     (write _test-input-stream "}\n")
  955     # convert
  956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  957     # registers except esp clobbered at this point
  958     # restore ed
  959     89/<- %edx 4/r32/esp
  960     (flush _test-output-buffered-file)
  961     (flush _test-error-buffered-file)
  962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
  968     # check output
  969     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  970     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  971     # check that stop(1) was called
  972     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  973     # don't restore from ebp
  974     81 0/subop/add %esp 8/imm32
  975     # . epilogue
  976     5d/pop-to-ebp
  977     c3/return
  978 
  979 test-function-with-addr-inout-3:
  980     # . prologue
  981     55/push-ebp
  982     89/<- %ebp 4/r32/esp
  983     # setup
  984     (clear-stream _test-input-stream)
  985     (clear-stream $_test-input-buffered-file->buffer)
  986     (clear-stream _test-output-stream)
  987     (clear-stream $_test-output-buffered-file->buffer)
  988     (clear-stream _test-error-stream)
  989     (clear-stream $_test-error-buffered-file->buffer)
  990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  991     68/push 0/imm32
  992     68/push 0/imm32
  993     89/<- %edx 4/r32/esp
  994     (tailor-exit-descriptor %edx 0x10)
  995     #
  996     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  997     (write _test-input-stream "}\n")
  998     # convert
  999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1000     # registers except esp clobbered at this point
 1001     # restore ed
 1002     89/<- %edx 4/r32/esp
 1003     (flush _test-output-buffered-file)
 1004     (flush _test-error-buffered-file)
 1005 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1011     # check output
 1012     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1013     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1014     # check that stop(1) was called
 1015     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1016     # don't restore from ebp
 1017     81 0/subop/add %esp 8/imm32
 1018     # . epilogue
 1019     5d/pop-to-ebp
 1020     c3/return
 1021 
 1022 test-function-with-addr-inout-4:
 1023     # . prologue
 1024     55/push-ebp
 1025     89/<- %ebp 4/r32/esp
 1026     # setup
 1027     (clear-stream _test-input-stream)
 1028     (clear-stream $_test-input-buffered-file->buffer)
 1029     (clear-stream _test-output-stream)
 1030     (clear-stream $_test-output-buffered-file->buffer)
 1031     (clear-stream _test-error-stream)
 1032     (clear-stream $_test-error-buffered-file->buffer)
 1033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1034     68/push 0/imm32
 1035     68/push 0/imm32
 1036     89/<- %edx 4/r32/esp
 1037     (tailor-exit-descriptor %edx 0x10)
 1038     #
 1039     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1040     (write _test-input-stream "}\n")
 1041     # convert
 1042     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1043     # registers except esp clobbered at this point
 1044     # restore ed
 1045     89/<- %edx 4/r32/esp
 1046     (flush _test-output-buffered-file)
 1047     (flush _test-error-buffered-file)
 1048 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1054     # check output
 1055     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1056     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1057     # check that stop(1) was called
 1058     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1059     # don't restore from ebp
 1060     81 0/subop/add %esp 8/imm32
 1061     # . epilogue
 1062     5d/pop-to-ebp
 1063     c3/return
 1064 
 1065 # 'main' is an exception
 1066 test-function-main-with-addr-inout:
 1067     # . prologue
 1068     55/push-ebp
 1069     89/<- %ebp 4/r32/esp
 1070     # setup
 1071     (clear-stream _test-input-stream)
 1072     (clear-stream $_test-input-buffered-file->buffer)
 1073     (clear-stream _test-output-stream)
 1074     (clear-stream $_test-output-buffered-file->buffer)
 1075     #
 1076     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1077     (write _test-input-stream "}\n")
 1078     # convert
 1079     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1080     (flush _test-output-buffered-file)
 1081     # no errors
 1082     # . epilogue
 1083     89/<- %esp 5/r32/ebp
 1084     5d/pop-to-ebp
 1085     c3/return
 1086 
 1087 # 'lookup' is an exception, but only in signatures
 1088 test-signature-lookup-with-addr-inout:
 1089     # . prologue
 1090     55/push-ebp
 1091     89/<- %ebp 4/r32/esp
 1092     # setup
 1093     (clear-stream _test-input-stream)
 1094     (clear-stream $_test-input-buffered-file->buffer)
 1095     (clear-stream _test-output-stream)
 1096     (clear-stream $_test-output-buffered-file->buffer)
 1097     #
 1098     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1099     # convert
 1100     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1101     (flush _test-output-buffered-file)
 1102     # no errors
 1103     # . epilogue
 1104     89/<- %esp 5/r32/ebp
 1105     5d/pop-to-ebp
 1106     c3/return
 1107 
 1108 test-convert-function-with-arg-and-body:
 1109     # . prologue
 1110     55/push-ebp
 1111     89/<- %ebp 4/r32/esp
 1112     # setup
 1113     (clear-stream _test-input-stream)
 1114     (clear-stream $_test-input-buffered-file->buffer)
 1115     (clear-stream _test-output-stream)
 1116     (clear-stream $_test-output-buffered-file->buffer)
 1117     #
 1118     (write _test-input-stream "fn foo n: int {\n")
 1119     (write _test-input-stream "  increment n\n")
 1120     (write _test-input-stream "}\n")
 1121     # convert
 1122     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1123     (flush _test-output-buffered-file)
 1124 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1130     # check output
 1131     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1132     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1133     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1134     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1135     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1136     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1137     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1138     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1140     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1141     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1142     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1143     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1144     # . epilogue
 1145     89/<- %esp 5/r32/ebp
 1146     5d/pop-to-ebp
 1147     c3/return
 1148 
 1149 test-convert-function-distinguishes-args:
 1150     # . prologue
 1151     55/push-ebp
 1152     89/<- %ebp 4/r32/esp
 1153     # setup
 1154     (clear-stream _test-input-stream)
 1155     (clear-stream $_test-input-buffered-file->buffer)
 1156     (clear-stream _test-output-stream)
 1157     (clear-stream $_test-output-buffered-file->buffer)
 1158     #
 1159     (write _test-input-stream "fn foo a: int, b: int {\n")
 1160     (write _test-input-stream "  increment b\n")
 1161     (write _test-input-stream "}\n")
 1162     # convert
 1163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1164     (flush _test-output-buffered-file)
 1165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1171     # check output
 1172     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1177     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1178     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1179     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1180     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1181     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1182     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1183     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1184     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1185     # . epilogue
 1186     89/<- %esp 5/r32/ebp
 1187     5d/pop-to-ebp
 1188     c3/return
 1189 
 1190 test-convert-function-with-return-literal:
 1191     # . prologue
 1192     55/push-ebp
 1193     89/<- %ebp 4/r32/esp
 1194     # setup
 1195     (clear-stream _test-input-stream)
 1196     (clear-stream $_test-input-buffered-file->buffer)
 1197     (clear-stream _test-output-stream)
 1198     (clear-stream $_test-output-buffered-file->buffer)
 1199     #
 1200     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1201     (write _test-input-stream "  return 0\n")
 1202     (write _test-input-stream "}\n")
 1203     # convert
 1204     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1205     (flush _test-output-buffered-file)
 1206 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1212     # check output
 1213     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1214     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1215     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1216     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1217     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1219     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1220     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1224     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1227     # . epilogue
 1228     89/<- %esp 5/r32/ebp
 1229     5d/pop-to-ebp
 1230     c3/return
 1231 
 1232 test-convert-function-with-return:
 1233     # . prologue
 1234     55/push-ebp
 1235     89/<- %ebp 4/r32/esp
 1236     # setup
 1237     (clear-stream _test-input-stream)
 1238     (clear-stream $_test-input-buffered-file->buffer)
 1239     (clear-stream _test-output-stream)
 1240     (clear-stream $_test-output-buffered-file->buffer)
 1241     #
 1242     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1243     (write _test-input-stream "  var y: int\n")
 1244     (write _test-input-stream "  return y\n")
 1245     (write _test-input-stream "}\n")
 1246     # convert
 1247     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1248     (flush _test-output-buffered-file)
 1249 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1255     # check output
 1256     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1257     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1258     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1259     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1260     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1261     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1262     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1263     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1264     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1265     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1266     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1267     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1268     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1269     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1270     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1271     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1272     # . epilogue
 1273     89/<- %esp 5/r32/ebp
 1274     5d/pop-to-ebp
 1275     c3/return
 1276 
 1277 test-convert-function-with-return-float:
 1278     # . prologue
 1279     55/push-ebp
 1280     89/<- %ebp 4/r32/esp
 1281     # setup
 1282     (clear-stream _test-input-stream)
 1283     (clear-stream $_test-input-buffered-file->buffer)
 1284     (clear-stream _test-output-stream)
 1285     (clear-stream $_test-output-buffered-file->buffer)
 1286     #
 1287     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1288     (write _test-input-stream "  var y: float\n")
 1289     (write _test-input-stream "  return y\n")
 1290     (write _test-input-stream "}\n")
 1291     # convert
 1292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1293     (flush _test-output-buffered-file)
 1294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1300     # check output
 1301     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1302     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1305     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1307     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1308     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
 1309     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1310     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1311     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1314     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1315     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1316     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1317     # . epilogue
 1318     89/<- %esp 5/r32/ebp
 1319     5d/pop-to-ebp
 1320     c3/return
 1321 
 1322 test-convert-function-with-return-register:
 1323     # . prologue
 1324     55/push-ebp
 1325     89/<- %ebp 4/r32/esp
 1326     # setup
 1327     (clear-stream _test-input-stream)
 1328     (clear-stream $_test-input-buffered-file->buffer)
 1329     (clear-stream _test-output-stream)
 1330     (clear-stream $_test-output-buffered-file->buffer)
 1331     #
 1332     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1333     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1334     (write _test-input-stream "  return y\n")
 1335     (write _test-input-stream "}\n")
 1336     # convert
 1337     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1338     (flush _test-output-buffered-file)
 1339 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1345     # check output
 1346     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1347     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1348     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1349     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1350     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1351     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1352     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1353     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1354     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1355     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1356     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1357     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1359     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1360     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1361     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1362     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1363     # . epilogue
 1364     89/<- %esp 5/r32/ebp
 1365     5d/pop-to-ebp
 1366     c3/return
 1367 
 1368 test-function-with-output-without-register:
 1369     # . prologue
 1370     55/push-ebp
 1371     89/<- %ebp 4/r32/esp
 1372     # setup
 1373     (clear-stream _test-input-stream)
 1374     (clear-stream $_test-input-buffered-file->buffer)
 1375     (clear-stream _test-output-stream)
 1376     (clear-stream $_test-output-buffered-file->buffer)
 1377     (clear-stream _test-error-stream)
 1378     (clear-stream $_test-error-buffered-file->buffer)
 1379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1380     68/push 0/imm32
 1381     68/push 0/imm32
 1382     89/<- %edx 4/r32/esp
 1383     (tailor-exit-descriptor %edx 0x10)
 1384     #
 1385     (write _test-input-stream "fn foo -> _: int {\n")
 1386     (write _test-input-stream "}\n")
 1387     # convert
 1388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1389     # registers except esp clobbered at this point
 1390     # restore ed
 1391     89/<- %edx 4/r32/esp
 1392     (flush _test-output-buffered-file)
 1393     (flush _test-error-buffered-file)
 1394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1400     # check output
 1401     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1402     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1403     # check that stop(1) was called
 1404     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1405     # don't restore from ebp
 1406     81 0/subop/add %esp 8/imm32
 1407     # . epilogue
 1408     5d/pop-to-ebp
 1409     c3/return
 1410 
 1411 test-function-with-outputs-in-conflicting-registers:
 1412     # . prologue
 1413     55/push-ebp
 1414     89/<- %ebp 4/r32/esp
 1415     # setup
 1416     (clear-stream _test-input-stream)
 1417     (clear-stream $_test-input-buffered-file->buffer)
 1418     (clear-stream _test-output-stream)
 1419     (clear-stream $_test-output-buffered-file->buffer)
 1420     (clear-stream _test-error-stream)
 1421     (clear-stream $_test-error-buffered-file->buffer)
 1422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1423     68/push 0/imm32
 1424     68/push 0/imm32
 1425     89/<- %edx 4/r32/esp
 1426     (tailor-exit-descriptor %edx 0x10)
 1427     #
 1428     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1429     (write _test-input-stream "}\n")
 1430     # convert
 1431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1432     # registers except esp clobbered at this point
 1433     # restore ed
 1434     89/<- %edx 4/r32/esp
 1435     (flush _test-output-buffered-file)
 1436     (flush _test-error-buffered-file)
 1437 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1443     # check output
 1444     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1445     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1446     # check that stop(1) was called
 1447     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1448     # don't restore from ebp
 1449     81 0/subop/add %esp 8/imm32
 1450     # . epilogue
 1451     5d/pop-to-ebp
 1452     c3/return
 1453 
 1454 test-function-with-named-output:
 1455     # . prologue
 1456     55/push-ebp
 1457     89/<- %ebp 4/r32/esp
 1458     # setup
 1459     (clear-stream _test-input-stream)
 1460     (clear-stream $_test-input-buffered-file->buffer)
 1461     (clear-stream _test-output-stream)
 1462     (clear-stream $_test-output-buffered-file->buffer)
 1463     (clear-stream _test-error-stream)
 1464     (clear-stream $_test-error-buffered-file->buffer)
 1465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1466     68/push 0/imm32
 1467     68/push 0/imm32
 1468     89/<- %edx 4/r32/esp
 1469     (tailor-exit-descriptor %edx 0x10)
 1470     #
 1471     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1472     (write _test-input-stream "  return 0\n")
 1473     (write _test-input-stream "}\n")
 1474     # convert
 1475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1476     # registers except esp clobbered at this point
 1477     # restore ed
 1478     89/<- %edx 4/r32/esp
 1479     (flush _test-output-buffered-file)
 1480     (flush _test-error-buffered-file)
 1481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1487     # check output
 1488     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1489     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1490     # check that stop(1) was called
 1491     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1492     # don't restore from ebp
 1493     81 0/subop/add %esp 8/imm32
 1494     # . epilogue
 1495     5d/pop-to-ebp
 1496     c3/return
 1497 
 1498 test-return-with-wrong-type:
 1499     # . prologue
 1500     55/push-ebp
 1501     89/<- %ebp 4/r32/esp
 1502     # setup
 1503     (clear-stream _test-input-stream)
 1504     (clear-stream $_test-input-buffered-file->buffer)
 1505     (clear-stream _test-output-stream)
 1506     (clear-stream $_test-output-buffered-file->buffer)
 1507     (clear-stream _test-error-stream)
 1508     (clear-stream $_test-error-buffered-file->buffer)
 1509     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1510     68/push 0/imm32
 1511     68/push 0/imm32
 1512     89/<- %edx 4/r32/esp
 1513     (tailor-exit-descriptor %edx 0x10)
 1514     #
 1515     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1516     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1517     (write _test-input-stream "  return x\n")
 1518     (write _test-input-stream "}\n")
 1519     # convert
 1520     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1521     # registers except esp clobbered at this point
 1522     # restore ed
 1523     89/<- %edx 4/r32/esp
 1524     (flush _test-output-buffered-file)
 1525     (flush _test-error-buffered-file)
 1526 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1532     # check output
 1533     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1534     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1535     # check that stop(1) was called
 1536     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1537     # don't restore from ebp
 1538     81 0/subop/add %esp 8/imm32
 1539     # . epilogue
 1540     5d/pop-to-ebp
 1541     c3/return
 1542 
 1543 test-missing-return:
 1544     # . prologue
 1545     55/push-ebp
 1546     89/<- %ebp 4/r32/esp
 1547     # setup
 1548     (clear-stream _test-input-stream)
 1549     (clear-stream $_test-input-buffered-file->buffer)
 1550     (clear-stream _test-output-stream)
 1551     (clear-stream $_test-output-buffered-file->buffer)
 1552     (clear-stream _test-error-stream)
 1553     (clear-stream $_test-error-buffered-file->buffer)
 1554     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1555     68/push 0/imm32
 1556     68/push 0/imm32
 1557     89/<- %edx 4/r32/esp
 1558     (tailor-exit-descriptor %edx 0x10)
 1559     #
 1560     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1561     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1562     (write _test-input-stream "}\n")
 1563     # convert
 1564     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1565     # registers except esp clobbered at this point
 1566     # restore ed
 1567     89/<- %edx 4/r32/esp
 1568     (flush _test-output-buffered-file)
 1569     (flush _test-error-buffered-file)
 1570 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1576     # check output
 1577     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1578     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1579     # check that stop(1) was called
 1580     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1581     # don't restore from ebp
 1582     81 0/subop/add %esp 8/imm32
 1583     # . epilogue
 1584     5d/pop-to-ebp
 1585     c3/return
 1586 
 1587 test-missing-return-2:
 1588     # . prologue
 1589     55/push-ebp
 1590     89/<- %ebp 4/r32/esp
 1591     # setup
 1592     (clear-stream _test-input-stream)
 1593     (clear-stream $_test-input-buffered-file->buffer)
 1594     (clear-stream _test-output-stream)
 1595     (clear-stream $_test-output-buffered-file->buffer)
 1596     (clear-stream _test-error-stream)
 1597     (clear-stream $_test-error-buffered-file->buffer)
 1598     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1599     68/push 0/imm32
 1600     68/push 0/imm32
 1601     89/<- %edx 4/r32/esp
 1602     (tailor-exit-descriptor %edx 0x10)
 1603     #
 1604     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1605     (write _test-input-stream "}\n")
 1606     # convert
 1607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1608     # registers except esp clobbered at this point
 1609     # restore ed
 1610     89/<- %edx 4/r32/esp
 1611     (flush _test-output-buffered-file)
 1612     (flush _test-error-buffered-file)
 1613 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1619     # check output
 1620     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
 1621     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
 1622     # check that stop(1) was called
 1623     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
 1624     # don't restore from ebp
 1625     81 0/subop/add %esp 8/imm32
 1626     # . epilogue
 1627     5d/pop-to-ebp
 1628     c3/return
 1629 
 1630 test-early-exit-without-return:
 1631     # . prologue
 1632     55/push-ebp
 1633     89/<- %ebp 4/r32/esp
 1634     # setup
 1635     (clear-stream _test-input-stream)
 1636     (clear-stream $_test-input-buffered-file->buffer)
 1637     (clear-stream _test-output-stream)
 1638     (clear-stream $_test-output-buffered-file->buffer)
 1639     (clear-stream _test-error-stream)
 1640     (clear-stream $_test-error-buffered-file->buffer)
 1641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1642     68/push 0/imm32
 1643     68/push 0/imm32
 1644     89/<- %edx 4/r32/esp
 1645     (tailor-exit-descriptor %edx 0x10)
 1646     #
 1647     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1648     (write _test-input-stream "  break\n")
 1649     (write _test-input-stream "  return 0\n")
 1650     (write _test-input-stream "}\n")
 1651     # convert
 1652     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1653     # registers except esp clobbered at this point
 1654     # restore ed
 1655     89/<- %edx 4/r32/esp
 1656     (flush _test-output-buffered-file)
 1657     (flush _test-error-buffered-file)
 1658 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1664     # check output
 1665     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1666     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1667     # check that stop(1) was called
 1668     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1669     # don't restore from ebp
 1670     81 0/subop/add %esp 8/imm32
 1671     # . epilogue
 1672     5d/pop-to-ebp
 1673     c3/return
 1674 
 1675 test-return-with-too-few-inouts:
 1676     # . prologue
 1677     55/push-ebp
 1678     89/<- %ebp 4/r32/esp
 1679     # setup
 1680     (clear-stream _test-input-stream)
 1681     (clear-stream $_test-input-buffered-file->buffer)
 1682     (clear-stream _test-output-stream)
 1683     (clear-stream $_test-output-buffered-file->buffer)
 1684     (clear-stream _test-error-stream)
 1685     (clear-stream $_test-error-buffered-file->buffer)
 1686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1687     68/push 0/imm32
 1688     68/push 0/imm32
 1689     89/<- %edx 4/r32/esp
 1690     (tailor-exit-descriptor %edx 0x10)
 1691     #
 1692     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1693     (write _test-input-stream "  return\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-return-with-too-many-inouts:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     (clear-stream _test-error-stream)
 1729     (clear-stream $_test-error-buffered-file->buffer)
 1730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1731     68/push 0/imm32
 1732     68/push 0/imm32
 1733     89/<- %edx 4/r32/esp
 1734     (tailor-exit-descriptor %edx 0x10)
 1735     #
 1736     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1737     (write _test-input-stream "  return 0, 0\n")
 1738     (write _test-input-stream "}\n")
 1739     # convert
 1740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1741     # registers except esp clobbered at this point
 1742     # restore ed
 1743     89/<- %edx 4/r32/esp
 1744     (flush _test-output-buffered-file)
 1745     (flush _test-error-buffered-file)
 1746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1752     # check output
 1753     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1754     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1755     # check that stop(1) was called
 1756     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1757     # don't restore from ebp
 1758     81 0/subop/add %esp 8/imm32
 1759     # . epilogue
 1760     5d/pop-to-ebp
 1761     c3/return
 1762 
 1763 test-return-unavailable-value:
 1764     # . prologue
 1765     55/push-ebp
 1766     89/<- %ebp 4/r32/esp
 1767     # setup
 1768     (clear-stream _test-input-stream)
 1769     (clear-stream $_test-input-buffered-file->buffer)
 1770     (clear-stream _test-output-stream)
 1771     (clear-stream $_test-output-buffered-file->buffer)
 1772     (clear-stream _test-error-stream)
 1773     (clear-stream $_test-error-buffered-file->buffer)
 1774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1775     68/push 0/imm32
 1776     68/push 0/imm32
 1777     89/<- %edx 4/r32/esp
 1778     (tailor-exit-descriptor %edx 0x10)
 1779     #
 1780     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1781     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1782     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1783     (write _test-input-stream "  return y, x\n")
 1784     (write _test-input-stream "}\n")
 1785     # convert
 1786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1787     # registers except esp clobbered at this point
 1788     # restore ed
 1789     89/<- %edx 4/r32/esp
 1790     (flush _test-output-buffered-file)
 1791     (flush _test-error-buffered-file)
 1792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1798     # check output
 1799     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1800     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1801     # check that stop(1) was called
 1802     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1803     # don't restore from ebp
 1804     81 0/subop/add %esp 8/imm32
 1805     # . epilogue
 1806     5d/pop-to-ebp
 1807     c3/return
 1808 
 1809 test-return-literal-to-float:
 1810     # . prologue
 1811     55/push-ebp
 1812     89/<- %ebp 4/r32/esp
 1813     # setup
 1814     (clear-stream _test-input-stream)
 1815     (clear-stream $_test-input-buffered-file->buffer)
 1816     (clear-stream _test-output-stream)
 1817     (clear-stream $_test-output-buffered-file->buffer)
 1818     (clear-stream _test-error-stream)
 1819     (clear-stream $_test-error-buffered-file->buffer)
 1820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1821     68/push 0/imm32
 1822     68/push 0/imm32
 1823     89/<- %edx 4/r32/esp
 1824     (tailor-exit-descriptor %edx 0x10)
 1825     #
 1826     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
 1827     (write _test-input-stream "  return 0\n")
 1828     (write _test-input-stream "}\n")
 1829     # convert
 1830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1831     # registers except esp clobbered at this point
 1832     # restore ed
 1833     89/<- %edx 4/r32/esp
 1834     (flush _test-output-buffered-file)
 1835     (flush _test-error-buffered-file)
 1836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1842     # check output
 1843     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
 1844     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
 1845     # check that stop(1) was called
 1846     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
 1847     # don't restore from ebp
 1848     81 0/subop/add %esp 8/imm32
 1849     # . epilogue
 1850     5d/pop-to-ebp
 1851     c3/return
 1852 
 1853 test-convert-return-with-duplicate-values:
 1854     # . prologue
 1855     55/push-ebp
 1856     89/<- %ebp 4/r32/esp
 1857     # setup
 1858     (clear-stream _test-input-stream)
 1859     (clear-stream $_test-input-buffered-file->buffer)
 1860     (clear-stream _test-output-stream)
 1861     (clear-stream $_test-output-buffered-file->buffer)
 1862     #
 1863     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1864     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1865     (write _test-input-stream "  return x, x\n")
 1866     (write _test-input-stream "}\n")
 1867     # convert
 1868     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1869     (flush _test-output-buffered-file)
 1870 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1876     # check output
 1877     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1878     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1879     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1880     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1881     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1883     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1884     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1885     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1886     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1887     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1888     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1889     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1891     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1892     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1893     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1894     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1895     # . epilogue
 1896     89/<- %esp 5/r32/ebp
 1897     5d/pop-to-ebp
 1898     c3/return
 1899 
 1900 test-convert-return-with-duplicate-values-2:
 1901     # . prologue
 1902     55/push-ebp
 1903     89/<- %ebp 4/r32/esp
 1904     # setup
 1905     (clear-stream _test-input-stream)
 1906     (clear-stream $_test-input-buffered-file->buffer)
 1907     (clear-stream _test-output-stream)
 1908     (clear-stream $_test-output-buffered-file->buffer)
 1909     #
 1910     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1911     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1912     (write _test-input-stream "  return x, x\n")
 1913     (write _test-input-stream "}\n")
 1914     # convert
 1915     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1916     (flush _test-output-buffered-file)
 1917 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1923     # check output
 1924     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1925     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1926     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1927     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1928     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1930     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1931     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1932     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1933     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1934     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1935     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1936     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1937     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1938     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1939     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1940     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1941     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1942     # . epilogue
 1943     89/<- %esp 5/r32/ebp
 1944     5d/pop-to-ebp
 1945     c3/return
 1946 
 1947 test-stmt-with-unknown-var:
 1948     # . prologue
 1949     55/push-ebp
 1950     89/<- %ebp 4/r32/esp
 1951     # setup
 1952     (clear-stream _test-input-stream)
 1953     (clear-stream $_test-input-buffered-file->buffer)
 1954     (clear-stream _test-output-stream)
 1955     (clear-stream $_test-output-buffered-file->buffer)
 1956     (clear-stream _test-error-stream)
 1957     (clear-stream $_test-error-buffered-file->buffer)
 1958     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1959     68/push 0/imm32
 1960     68/push 0/imm32
 1961     89/<- %edx 4/r32/esp
 1962     (tailor-exit-descriptor %edx 0x10)
 1963     #
 1964     (write _test-input-stream "fn foo {\n")
 1965     (write _test-input-stream "  x <- copy 0x34\n")
 1966     (write _test-input-stream "}\n")
 1967     # convert
 1968     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1969     # registers except esp clobbered at this point
 1970     # restore ed
 1971     89/<- %edx 4/r32/esp
 1972     (flush _test-output-buffered-file)
 1973     (flush _test-error-buffered-file)
 1974 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1980     # check output
 1981     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1982     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1983     # check that stop(1) was called
 1984     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1985     # don't restore from ebp
 1986     81 0/subop/add %esp 8/imm32
 1987     # . epilogue
 1988     5d/pop-to-ebp
 1989     c3/return
 1990 
 1991 test-stmt-with-invalid-identifier:
 1992     # . prologue
 1993     55/push-ebp
 1994     89/<- %ebp 4/r32/esp
 1995     # setup
 1996     (clear-stream _test-input-stream)
 1997     (clear-stream $_test-input-buffered-file->buffer)
 1998     (clear-stream _test-output-stream)
 1999     (clear-stream $_test-output-buffered-file->buffer)
 2000     (clear-stream _test-error-stream)
 2001     (clear-stream $_test-error-buffered-file->buffer)
 2002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2003     68/push 0/imm32
 2004     68/push 0/imm32
 2005     89/<- %edx 4/r32/esp
 2006     (tailor-exit-descriptor %edx 0x10)
 2007     #
 2008     (write _test-input-stream "fn foo {\n")
 2009     (write _test-input-stream "  1 <- copy 0x34\n")
 2010     (write _test-input-stream "}\n")
 2011     # convert
 2012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2013     # registers except esp clobbered at this point
 2014     # restore ed
 2015     89/<- %edx 4/r32/esp
 2016     (flush _test-output-buffered-file)
 2017     (flush _test-error-buffered-file)
 2018 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2024     # check output
 2025     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 2026     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 2027     # check that stop(1) was called
 2028     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 2029     # don't restore from ebp
 2030     81 0/subop/add %esp 8/imm32
 2031     # . epilogue
 2032     5d/pop-to-ebp
 2033     c3/return
 2034 
 2035 test-stmt-with-deref-var:
 2036     # . prologue
 2037     55/push-ebp
 2038     89/<- %ebp 4/r32/esp
 2039     # setup
 2040     (clear-stream _test-input-stream)
 2041     (clear-stream $_test-input-buffered-file->buffer)
 2042     (clear-stream _test-output-stream)
 2043     (clear-stream $_test-output-buffered-file->buffer)
 2044     (clear-stream _test-error-stream)
 2045     (clear-stream $_test-error-buffered-file->buffer)
 2046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2047     68/push 0/imm32
 2048     68/push 0/imm32
 2049     89/<- %edx 4/r32/esp
 2050     (tailor-exit-descriptor %edx 0x10)
 2051     #
 2052     (write _test-input-stream "fn foo {\n")
 2053     (write _test-input-stream "  *x <- copy 0x34\n")
 2054     (write _test-input-stream "}\n")
 2055     # convert
 2056     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2057     # registers except esp clobbered at this point
 2058     # restore ed
 2059     89/<- %edx 4/r32/esp
 2060     (flush _test-output-buffered-file)
 2061     (flush _test-error-buffered-file)
 2062 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2068     # check output
 2069     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 2070     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 2071     # check that stop(1) was called
 2072     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 2073     # don't restore from ebp
 2074     81 0/subop/add %esp 8/imm32
 2075     # . epilogue
 2076     5d/pop-to-ebp
 2077     c3/return
 2078 
 2079 test-convert-function-with-literal-arg:
 2080     # . prologue
 2081     55/push-ebp
 2082     89/<- %ebp 4/r32/esp
 2083     # setup
 2084     (clear-stream _test-input-stream)
 2085     (clear-stream $_test-input-buffered-file->buffer)
 2086     (clear-stream _test-output-stream)
 2087     (clear-stream $_test-output-buffered-file->buffer)
 2088     #
 2089     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 2090     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2091     (write _test-input-stream "  result <- add 1\n")
 2092     (write _test-input-stream "  return result\n")
 2093     (write _test-input-stream "}\n")
 2094     # convert
 2095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2096     (flush _test-output-buffered-file)
 2097 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2103     # check output
 2104     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 2105     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 2106     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 2107     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 2108     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 2109     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 2110     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 2111     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 2112     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 2113     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 2114     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 2115     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 2116     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 2117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 2118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 2119     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 2120     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 2121     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 2122     # . epilogue
 2123     89/<- %esp 5/r32/ebp
 2124     5d/pop-to-ebp
 2125     c3/return
 2126 
 2127 test-convert-function-with-literal-arg-2:
 2128     # . prologue
 2129     55/push-ebp
 2130     89/<- %ebp 4/r32/esp
 2131     # setup
 2132     (clear-stream _test-input-stream)
 2133     (clear-stream $_test-input-buffered-file->buffer)
 2134     (clear-stream _test-output-stream)
 2135     (clear-stream $_test-output-buffered-file->buffer)
 2136     #
 2137     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2138     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2139     (write _test-input-stream "  result <- add 1\n")
 2140     (write _test-input-stream "  return result\n")
 2141     (write _test-input-stream "}\n")
 2142     # convert
 2143     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2144     (flush _test-output-buffered-file)
 2145 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2151     # check output
 2152     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2153     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2154     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2155     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2156     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2157     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2158     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2159     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2161     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2162     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2163     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2170     # . epilogue
 2171     89/<- %esp 5/r32/ebp
 2172     5d/pop-to-ebp
 2173     c3/return
 2174 
 2175 test-convert-function-call-with-literal-arg:
 2176     # . prologue
 2177     55/push-ebp
 2178     89/<- %ebp 4/r32/esp
 2179     # setup
 2180     (clear-stream _test-input-stream)
 2181     (clear-stream $_test-input-buffered-file->buffer)
 2182     (clear-stream _test-output-stream)
 2183     (clear-stream $_test-output-buffered-file->buffer)
 2184     #
 2185     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2186     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2187     (write _test-input-stream "  return result\n")
 2188     (write _test-input-stream "}\n")
 2189     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2190     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2191     (write _test-input-stream "  result <- add b\n")
 2192     (write _test-input-stream "  return result\n")
 2193     (write _test-input-stream "}\n")
 2194     # convert
 2195     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2196     (flush _test-output-buffered-file)
 2197 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2203     # check output
 2204     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2205     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2206     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2207     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2208     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2209     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2210     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2211     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2212     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2213     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2214     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2215     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2216     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2217     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2218     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2219     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2220     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2221     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2222     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2223     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2224     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2225     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2226     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2227     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2228     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2229     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2230     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2231     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2232     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2233     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2234     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2235     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2236     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2237     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2238     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2239     # . epilogue
 2240     89/<- %esp 5/r32/ebp
 2241     5d/pop-to-ebp
 2242     c3/return
 2243 
 2244 test-convert-function-call-with-literal-string-arg:
 2245     # . prologue
 2246     55/push-ebp
 2247     89/<- %ebp 4/r32/esp
 2248     # setup
 2249     (clear-stream _test-input-stream)
 2250     (clear-stream $_test-input-buffered-file->buffer)
 2251     (clear-stream _test-output-stream)
 2252     (clear-stream $_test-output-buffered-file->buffer)
 2253     #
 2254     (write _test-input-stream "fn foo {\n")
 2255     (write _test-input-stream "  string-func \"abc\"\n")
 2256     (write _test-input-stream "}\n")
 2257     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2258     # convert
 2259     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2260     # no errors
 2261     # not bothering checking output
 2262     # . epilogue
 2263     89/<- %esp 5/r32/ebp
 2264     5d/pop-to-ebp
 2265     c3/return
 2266 
 2267 test-convert-function-call-with-null-addr:
 2268     # . prologue
 2269     55/push-ebp
 2270     89/<- %ebp 4/r32/esp
 2271     # setup
 2272     (clear-stream _test-input-stream)
 2273     (clear-stream $_test-input-buffered-file->buffer)
 2274     (clear-stream _test-output-stream)
 2275     (clear-stream $_test-output-buffered-file->buffer)
 2276     #
 2277     (write _test-input-stream "fn foo {\n")
 2278     (write _test-input-stream "  bar 0\n")
 2279     (write _test-input-stream "}\n")
 2280     (write _test-input-stream "sig bar in: (addr int)\n")
 2281     # convert
 2282     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2283     # no errors
 2284     # not bothering checking output
 2285     # . epilogue
 2286     89/<- %esp 5/r32/ebp
 2287     5d/pop-to-ebp
 2288     c3/return
 2289 
 2290 test-convert-function-call-with-signature:
 2291     # . prologue
 2292     55/push-ebp
 2293     89/<- %ebp 4/r32/esp
 2294     # setup
 2295     (clear-stream _test-input-stream)
 2296     (clear-stream $_test-input-buffered-file->buffer)
 2297     (clear-stream _test-output-stream)
 2298     (clear-stream $_test-output-buffered-file->buffer)
 2299     #
 2300     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2301     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2302     (write _test-input-stream "  return result\n")
 2303     (write _test-input-stream "}\n")
 2304     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2305     # convert
 2306     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2307     (flush _test-output-buffered-file)
 2308 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2314     # check output
 2315     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2316     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2317     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2318     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2319     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2320     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2321     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2322     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2323     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2324     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2325     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2326     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2327     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2328     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2329     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2330     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2331     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2332     # . epilogue
 2333     89/<- %esp 5/r32/ebp
 2334     5d/pop-to-ebp
 2335     c3/return
 2336 
 2337 test-convert-function-with-local-var-in-mem:
 2338     # . prologue
 2339     55/push-ebp
 2340     89/<- %ebp 4/r32/esp
 2341     # setup
 2342     (clear-stream _test-input-stream)
 2343     (clear-stream $_test-input-buffered-file->buffer)
 2344     (clear-stream _test-output-stream)
 2345     (clear-stream $_test-output-buffered-file->buffer)
 2346     #
 2347     (write _test-input-stream "fn foo {\n")
 2348     (write _test-input-stream "  var x: int\n")
 2349     (write _test-input-stream "  increment x\n")
 2350     (write _test-input-stream "}\n")
 2351     # convert
 2352     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2353     (flush _test-output-buffered-file)
 2354 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2360     # check output
 2361     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2362     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2363     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2364     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2365     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2367     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2368     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2369     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem/8")
 2370     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2371     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2372     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2373     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2374     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2375     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2376     # . epilogue
 2377     89/<- %esp 5/r32/ebp
 2378     5d/pop-to-ebp
 2379     c3/return
 2380 
 2381 test-convert-invalid-literal:
 2382     # . prologue
 2383     55/push-ebp
 2384     89/<- %ebp 4/r32/esp
 2385     # setup
 2386     (clear-stream _test-input-stream)
 2387     (clear-stream $_test-input-buffered-file->buffer)
 2388     (clear-stream _test-output-stream)
 2389     (clear-stream $_test-output-buffered-file->buffer)
 2390     (clear-stream _test-error-stream)
 2391     (clear-stream $_test-error-buffered-file->buffer)
 2392     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2393     68/push 0/imm32
 2394     68/push 0/imm32
 2395     89/<- %edx 4/r32/esp
 2396     (tailor-exit-descriptor %edx 0x10)
 2397     #
 2398     (write _test-input-stream "fn foo {\n")
 2399     (write _test-input-stream "  increment 1n\n")
 2400     (write _test-input-stream "}\n")
 2401     # convert
 2402     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2403     # registers except esp clobbered at this point
 2404     # restore ed
 2405     89/<- %edx 4/r32/esp
 2406     (flush _test-output-buffered-file)
 2407     (flush _test-error-buffered-file)
 2408 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2414     # check output
 2415     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2416     (check-next-stream-line-equal _test-error-stream  "fn foo: variable '1n' cannot begin with a digit (or do you have a typo in a number?)"  "F - test-convert-invalid-literal: error message")
 2417     # check that stop(1) was called
 2418     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2419     # don't restore from ebp
 2420     81 0/subop/add %esp 8/imm32
 2421     # . epilogue
 2422     5d/pop-to-ebp
 2423     c3/return
 2424 
 2425 test-convert-valid-literal-with-metadata:
 2426     # . prologue
 2427     55/push-ebp
 2428     89/<- %ebp 4/r32/esp
 2429     # setup
 2430     (clear-stream _test-input-stream)
 2431     (clear-stream $_test-input-buffered-file->buffer)
 2432     (clear-stream _test-output-stream)
 2433     (clear-stream $_test-output-buffered-file->buffer)
 2434     #
 2435     (write _test-input-stream "fn foo {\n")
 2436     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
 2437     (write _test-input-stream "}\n")
 2438     # convert
 2439     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2440     (flush _test-output-buffered-file)
 2441 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2447     # no errors
 2448     # . epilogue
 2449     89/<- %esp 5/r32/ebp
 2450     5d/pop-to-ebp
 2451     c3/return
 2452 
 2453 test-local-var-in-mem-has-no-initializer:
 2454     # . prologue
 2455     55/push-ebp
 2456     89/<- %ebp 4/r32/esp
 2457     # setup
 2458     (clear-stream _test-input-stream)
 2459     (clear-stream $_test-input-buffered-file->buffer)
 2460     (clear-stream _test-output-stream)
 2461     (clear-stream $_test-output-buffered-file->buffer)
 2462     (clear-stream _test-error-stream)
 2463     (clear-stream $_test-error-buffered-file->buffer)
 2464     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2465     68/push 0/imm32
 2466     68/push 0/imm32
 2467     89/<- %edx 4/r32/esp
 2468     (tailor-exit-descriptor %edx 0x10)
 2469     #
 2470     (write _test-input-stream "fn foo {\n")
 2471     (write _test-input-stream "  var x: int <- copy 0\n")
 2472     (write _test-input-stream "  increment x\n")
 2473     (write _test-input-stream "}\n")
 2474     # convert
 2475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2476     # registers except esp clobbered at this point
 2477     # restore ed
 2478     89/<- %edx 4/r32/esp
 2479     (flush _test-output-buffered-file)
 2480     (flush _test-error-buffered-file)
 2481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2487     # check output
 2488     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2489     (check-next-stream-line-equal _test-error-stream  "fn foo: var x: variables on the stack can't take an initializer"  "F - test-var-in-mem-has-no-initializer: error message")
 2490     # check that stop(1) was called
 2491     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2492     # don't restore from ebp
 2493     81 0/subop/add %esp 8/imm32
 2494     # . epilogue
 2495     5d/pop-to-ebp
 2496     c3/return
 2497 
 2498 test-convert-function-with-local-var-with-compound-type-in-mem:
 2499     # . prologue
 2500     55/push-ebp
 2501     89/<- %ebp 4/r32/esp
 2502     # setup
 2503     (clear-stream _test-input-stream)
 2504     (clear-stream $_test-input-buffered-file->buffer)
 2505     (clear-stream _test-output-stream)
 2506     (clear-stream $_test-output-buffered-file->buffer)
 2507     #
 2508     (write _test-input-stream "fn foo {\n")
 2509     (write _test-input-stream "  var x: (addr int)\n")
 2510     (write _test-input-stream "  copy-to x, 0\n")
 2511     (write _test-input-stream "}\n")
 2512     # convert
 2513     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2514     (flush _test-output-buffered-file)
 2515 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2521     # check output
 2522     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2523     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2524     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2525     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/3")
 2526     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2527     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2528     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-compound-type-in-mem/6")
 2529     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy *(ebp+0xfffffffc) 0/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/7")
 2530     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/8")
 2531     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2532     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2533     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2534     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/12")
 2535     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-compound-type-in-mem/13")
 2536     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2537     # . epilogue
 2538     89/<- %esp 5/r32/ebp
 2539     5d/pop-to-ebp
 2540     c3/return
 2541 
 2542 test-convert-function-with-local-var-in-reg:
 2543     # . prologue
 2544     55/push-ebp
 2545     89/<- %ebp 4/r32/esp
 2546     # setup
 2547     (clear-stream _test-input-stream)
 2548     (clear-stream $_test-input-buffered-file->buffer)
 2549     (clear-stream _test-output-stream)
 2550     (clear-stream $_test-output-buffered-file->buffer)
 2551     #
 2552     (write _test-input-stream "fn foo {\n")
 2553     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2554     (write _test-input-stream "  x <- increment\n")
 2555     (write _test-input-stream "}\n")
 2556     # convert
 2557     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2558     (flush _test-output-buffered-file)
 2559 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2565     # check output
 2566     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2567     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2568     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2569     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2570     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2571     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2572     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2573     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2574     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2575     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2576     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2577     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2582     # . epilogue
 2583     89/<- %esp 5/r32/ebp
 2584     5d/pop-to-ebp
 2585     c3/return
 2586 
 2587 test-convert-function-with-local-var-in-same-reg:
 2588     # . prologue
 2589     55/push-ebp
 2590     89/<- %ebp 4/r32/esp
 2591     # setup
 2592     (clear-stream _test-input-stream)
 2593     (clear-stream $_test-input-buffered-file->buffer)
 2594     (clear-stream _test-output-stream)
 2595     (clear-stream $_test-output-buffered-file->buffer)
 2596     #
 2597     (write _test-input-stream "fn foo {\n")
 2598     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2599     (write _test-input-stream "  var y/ecx: int <- copy x\n")
 2600     (write _test-input-stream "}\n")
 2601     # convert
 2602     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2603     (flush _test-output-buffered-file)
 2604 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2610     # check output
 2611     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
 2612     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
 2613     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
 2614     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
 2615     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
 2616     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
 2617     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
 2618     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-same-reg/7")
 2619     # optimization: skip the second copy
 2620     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
 2621     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
 2622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
 2623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
 2624     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
 2625     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
 2626     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
 2627     # . epilogue
 2628     89/<- %esp 5/r32/ebp
 2629     5d/pop-to-ebp
 2630     c3/return
 2631 
 2632 test-convert-function-with-local-var-in-same-reg-dereferenced:
 2633     # . prologue
 2634     55/push-ebp
 2635     89/<- %ebp 4/r32/esp
 2636     # setup
 2637     (clear-stream _test-input-stream)
 2638     (clear-stream $_test-input-buffered-file->buffer)
 2639     (clear-stream _test-output-stream)
 2640     (clear-stream $_test-output-buffered-file->buffer)
 2641     #
 2642     (write _test-input-stream "fn foo {\n")
 2643     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2644     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
 2645     (write _test-input-stream "}\n")
 2646     # convert
 2647     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2648     (flush _test-output-buffered-file)
 2649 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2655     # check output
 2656     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
 2657     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
 2658     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
 2659     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/3")
 2660     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
 2661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
 2662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/6")
 2663     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/7")
 2664     (check-next-stream-line-equal _test-output-stream "    8b/-> *ecx 0x00000001/r32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/8")  # don't optimize this away
 2665     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg-dereferenced/9")
 2666     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
 2667     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
 2668     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
 2669     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/13")
 2670     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
 2671     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
 2672     # . epilogue
 2673     89/<- %esp 5/r32/ebp
 2674     5d/pop-to-ebp
 2675     c3/return
 2676 
 2677 test-float-var-in-wrong-register:
 2678     # . prologue
 2679     55/push-ebp
 2680     89/<- %ebp 4/r32/esp
 2681     # setup
 2682     (clear-stream _test-input-stream)
 2683     (clear-stream $_test-input-buffered-file->buffer)
 2684     (clear-stream _test-output-stream)
 2685     (clear-stream $_test-output-buffered-file->buffer)
 2686     (clear-stream _test-error-stream)
 2687     (clear-stream $_test-error-buffered-file->buffer)
 2688     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2689     68/push 0/imm32
 2690     68/push 0/imm32
 2691     89/<- %edx 4/r32/esp
 2692     (tailor-exit-descriptor %edx 0x10)
 2693     #
 2694     (write _test-input-stream "fn foo {\n")
 2695     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2696     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2697     (write _test-input-stream "}\n")
 2698     # convert
 2699     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2700     # registers except esp clobbered at this point
 2701     # restore ed
 2702     89/<- %edx 4/r32/esp
 2703     (flush _test-output-buffered-file)
 2704     (flush _test-error-buffered-file)
 2705 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2711     # check output
 2712     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2713     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
 2714     # check that stop(1) was called
 2715     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2716     # don't restore from ebp
 2717     81 0/subop/add %esp 8/imm32
 2718     # . epilogue
 2719     5d/pop-to-ebp
 2720     c3/return
 2721 
 2722 test-non-float-var-in-wrong-register:
 2723     # . prologue
 2724     55/push-ebp
 2725     89/<- %ebp 4/r32/esp
 2726     # setup
 2727     (clear-stream _test-input-stream)
 2728     (clear-stream $_test-input-buffered-file->buffer)
 2729     (clear-stream _test-output-stream)
 2730     (clear-stream $_test-output-buffered-file->buffer)
 2731     (clear-stream _test-error-stream)
 2732     (clear-stream $_test-error-buffered-file->buffer)
 2733     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2734     68/push 0/imm32
 2735     68/push 0/imm32
 2736     89/<- %edx 4/r32/esp
 2737     (tailor-exit-descriptor %edx 0x10)
 2738     #
 2739     (write _test-input-stream "fn foo {\n")
 2740     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2741     (write _test-input-stream "}\n")
 2742     # convert
 2743     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2744     # registers except esp clobbered at this point
 2745     # restore ed
 2746     89/<- %edx 4/r32/esp
 2747     (flush _test-output-buffered-file)
 2748     (flush _test-error-buffered-file)
 2749 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2755     # check output
 2756     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2757     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
 2758     # check that stop(1) was called
 2759     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2760     # don't restore from ebp
 2761     81 0/subop/add %esp 8/imm32
 2762     # . epilogue
 2763     5d/pop-to-ebp
 2764     c3/return
 2765 
 2766 test-convert-function-with-allocate:
 2767     # . prologue
 2768     55/push-ebp
 2769     89/<- %ebp 4/r32/esp
 2770     # setup
 2771     (clear-stream _test-input-stream)
 2772     (clear-stream $_test-input-buffered-file->buffer)
 2773     (clear-stream _test-output-stream)
 2774     (clear-stream $_test-output-buffered-file->buffer)
 2775     #
 2776     (write _test-input-stream "fn foo {\n")
 2777     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2778     (write _test-input-stream "  allocate x\n")
 2779     (write _test-input-stream "}\n")
 2780     # convert
 2781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2782     (flush _test-output-buffered-file)
 2783 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2789     # check output
 2790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2797     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2798     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2799     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2800     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2801     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2802     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2803     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2804     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2805     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2806     # . epilogue
 2807     89/<- %esp 5/r32/ebp
 2808     5d/pop-to-ebp
 2809     c3/return
 2810 
 2811 test-initializer-in-hex:
 2812     # . prologue
 2813     55/push-ebp
 2814     89/<- %ebp 4/r32/esp
 2815     # setup
 2816     (clear-stream _test-input-stream)
 2817     (clear-stream $_test-input-buffered-file->buffer)
 2818     (clear-stream _test-output-stream)
 2819     (clear-stream $_test-output-buffered-file->buffer)
 2820     (clear-stream _test-error-stream)
 2821     (clear-stream $_test-error-buffered-file->buffer)
 2822     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2823     68/push 0/imm32
 2824     68/push 0/imm32
 2825     89/<- %edx 4/r32/esp
 2826     (tailor-exit-descriptor %edx 0x10)
 2827     #
 2828     (write _test-input-stream "fn foo {\n")
 2829     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2830     (write _test-input-stream "}\n")
 2831     # convert
 2832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2833     # registers except esp clobbered at this point
 2834     # restore ed
 2835     89/<- %edx 4/r32/esp
 2836     (flush _test-output-buffered-file)
 2837     (flush _test-error-buffered-file)
 2838 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2844     # check output
 2845     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2846     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-initializer-in-hex: error message")
 2847     # check that stop(1) was called
 2848     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2849     # don't restore from ebp
 2850     81 0/subop/add %esp 8/imm32
 2851     # . epilogue
 2852     5d/pop-to-ebp
 2853     c3/return
 2854 
 2855 test-convert-function-with-second-local-var-in-same-reg:
 2856     # . prologue
 2857     55/push-ebp
 2858     89/<- %ebp 4/r32/esp
 2859     # setup
 2860     (clear-stream _test-input-stream)
 2861     (clear-stream $_test-input-buffered-file->buffer)
 2862     (clear-stream _test-output-stream)
 2863     (clear-stream $_test-output-buffered-file->buffer)
 2864     #
 2865     (write _test-input-stream "fn foo {\n")
 2866     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2867     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2868     (write _test-input-stream "  y <- increment\n")
 2869     (write _test-input-stream "}\n")
 2870     # convert
 2871     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2872     (flush _test-output-buffered-file)
 2873 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2879     # check output
 2880     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2881     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2882     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2883     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-second-local-var-in-same-reg/3")
 2884     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2885     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2886     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-second-local-var-in-same-reg/6")
 2887     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/7")
 2888     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/8")
 2889     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2890     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/10")
 2891     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2893     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2894     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-second-local-var-in-same-reg/14")
 2895     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2896     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2897     # . epilogue
 2898     89/<- %esp 5/r32/ebp
 2899     5d/pop-to-ebp
 2900     c3/return
 2901 
 2902 test-read-clobbered-reg-var:
 2903     # . prologue
 2904     55/push-ebp
 2905     89/<- %ebp 4/r32/esp
 2906     # setup
 2907     (clear-stream _test-input-stream)
 2908     (clear-stream $_test-input-buffered-file->buffer)
 2909     (clear-stream _test-output-stream)
 2910     (clear-stream $_test-output-buffered-file->buffer)
 2911     (clear-stream _test-error-stream)
 2912     (clear-stream $_test-error-buffered-file->buffer)
 2913     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2914     68/push 0/imm32
 2915     68/push 0/imm32
 2916     89/<- %edx 4/r32/esp
 2917     (tailor-exit-descriptor %edx 0x10)
 2918     #
 2919     (write _test-input-stream "fn foo {\n")
 2920     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2921     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2922     (write _test-input-stream "  x <- increment\n")
 2923     (write _test-input-stream "}\n")
 2924     # convert
 2925     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2926     # registers except esp clobbered at this point
 2927     # restore ed
 2928     89/<- %edx 4/r32/esp
 2929     (flush _test-output-buffered-file)
 2930     (flush _test-error-buffered-file)
 2931 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2937     # check output
 2938     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2939     (check-next-stream-line-equal _test-error-stream  "fn foo: register ecx reads var 'x' after writing var 'y'"  "F - test-read-clobbered-reg-var: error message")
 2940     # check that stop(1) was called
 2941     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2942     # don't restore from ebp
 2943     81 0/subop/add %esp 8/imm32
 2944     # . epilogue
 2945     5d/pop-to-ebp
 2946     c3/return
 2947 
 2948 test-overlapping-int-fp-registers:
 2949     # . prologue
 2950     55/push-ebp
 2951     89/<- %ebp 4/r32/esp
 2952     # setup
 2953     (clear-stream _test-input-stream)
 2954     (clear-stream $_test-input-buffered-file->buffer)
 2955     (clear-stream _test-output-stream)
 2956     (clear-stream $_test-output-buffered-file->buffer)
 2957     (clear-stream _test-error-stream)
 2958     (clear-stream $_test-error-buffered-file->buffer)
 2959     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2960     68/push 0/imm32
 2961     68/push 0/imm32
 2962     89/<- %edx 4/r32/esp
 2963     (tailor-exit-descriptor %edx 0x10)
 2964     #
 2965     (write _test-input-stream "fn foo {\n")
 2966     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2967     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2968     (write _test-input-stream "  x <- increment\n")
 2969     (write _test-input-stream "}\n")
 2970     # convert
 2971     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2972     # registers except esp clobbered at this point
 2973     # restore ed
 2974     89/<- %edx 4/r32/esp
 2975     (flush _test-output-buffered-file)
 2976     (flush _test-error-buffered-file)
 2977 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2983     # no errors
 2984     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2985     # don't bother checking the generated code
 2986     # don't restore from ebp
 2987     81 0/subop/add %esp 8/imm32
 2988     # . epilogue
 2989     5d/pop-to-ebp
 2990     c3/return
 2991 
 2992 test-convert-function-call:
 2993     # . prologue
 2994     55/push-ebp
 2995     89/<- %ebp 4/r32/esp
 2996     # setup
 2997     (clear-stream _test-input-stream)
 2998     (clear-stream $_test-input-buffered-file->buffer)
 2999     (clear-stream _test-output-stream)
 3000     (clear-stream $_test-output-buffered-file->buffer)
 3001     #
 3002     (write _test-input-stream "fn main -> _/ebx: int {\n")
 3003     (write _test-input-stream "  var result/ebx: int <- foo\n")
 3004     (write _test-input-stream "  return result\n")
 3005     (write _test-input-stream "}\n")
 3006     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 3007     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 3008     (write _test-input-stream "  return result\n")
 3009     (write _test-input-stream "}\n")
 3010     # convert
 3011     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3012     (flush _test-output-buffered-file)
 3013 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3019     # check output
 3020     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 3021     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 3022     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 3023     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 3024     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 3025     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 3026     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3027     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 3028     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3029     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3030     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3031     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 3032     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 3033     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 3034     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 3035     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 3036     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 3037     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 3038     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 3039     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 3040     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 3041     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 3042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 3043     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 3044     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 3045     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 3046     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 3047     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 3048     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 3049     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 3050     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 3051     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 3052     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 3053     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 3054     # . epilogue
 3055     89/<- %esp 5/r32/ebp
 3056     5d/pop-to-ebp
 3057     c3/return
 3058 
 3059 test-convert-function-call-with-inout-with-compound-type:
 3060     # . prologue
 3061     55/push-ebp
 3062     89/<- %ebp 4/r32/esp
 3063     # setup
 3064     (clear-stream _test-input-stream)
 3065     (clear-stream $_test-input-buffered-file->buffer)
 3066     (clear-stream _test-output-stream)
 3067     (clear-stream $_test-output-buffered-file->buffer)
 3068     #
 3069     (write _test-input-stream "fn f {\n")
 3070     (write _test-input-stream "  var x: (addr int)\n")
 3071     (write _test-input-stream "  g x\n")
 3072     (write _test-input-stream "}\n")
 3073     (write _test-input-stream "fn g a: (addr int) {\n")
 3074     (write _test-input-stream "}\n")
 3075     # convert
 3076     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3077     (flush _test-output-buffered-file)
 3078 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3084     # check output
 3085     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 3086     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 3087     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 3088     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 3089     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 3090     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 3091     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 3092     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 3093     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-call-with-inout-with-compound-type/8")
 3094     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 3095     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 3096     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 3097     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 3098     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 3099     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 3100     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 3101     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 3102     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 3103     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 3104     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 3105     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 3106     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 3107     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 3108     # . epilogue
 3109     89/<- %esp 5/r32/ebp
 3110     5d/pop-to-ebp
 3111     c3/return
 3112 
 3113 test-convert-function-call-with-inout-with-type-parameter:
 3114     # . prologue
 3115     55/push-ebp
 3116     89/<- %ebp 4/r32/esp
 3117     # setup
 3118     (clear-stream _test-input-stream)
 3119     (clear-stream $_test-input-buffered-file->buffer)
 3120     (clear-stream _test-output-stream)
 3121     (clear-stream $_test-output-buffered-file->buffer)
 3122     (clear-stream _test-error-stream)
 3123     (clear-stream $_test-error-buffered-file->buffer)
 3124     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3125     68/push 0/imm32
 3126     68/push 0/imm32
 3127     89/<- %edx 4/r32/esp
 3128     (tailor-exit-descriptor %edx 0x10)
 3129     #
 3130     (write _test-input-stream "fn f {\n")
 3131     (write _test-input-stream "  var x: (addr int)\n")
 3132     (write _test-input-stream "  g x\n")
 3133     (write _test-input-stream "}\n")
 3134     (write _test-input-stream "fn g a: (addr _) {\n")
 3135     (write _test-input-stream "}\n")
 3136     # convert
 3137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3138     # registers except esp clobbered at this point
 3139     # restore ed
 3140     89/<- %edx 4/r32/esp
 3141     (flush _test-output-buffered-file)
 3142     (flush _test-error-buffered-file)
 3143 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3149     # no error; types matched
 3150     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 3151     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3152     # don't restore from ebp
 3153     81 0/subop/add %esp 8/imm32
 3154     # . epilogue
 3155     5d/pop-to-ebp
 3156     c3/return
 3157 
 3158 test-convert-function-call-with-incorrect-inout-type:
 3159     # . prologue
 3160     55/push-ebp
 3161     89/<- %ebp 4/r32/esp
 3162     # setup
 3163     (clear-stream _test-input-stream)
 3164     (clear-stream $_test-input-buffered-file->buffer)
 3165     (clear-stream _test-output-stream)
 3166     (clear-stream $_test-output-buffered-file->buffer)
 3167     (clear-stream _test-error-stream)
 3168     (clear-stream $_test-error-buffered-file->buffer)
 3169     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3170     68/push 0/imm32
 3171     68/push 0/imm32
 3172     89/<- %edx 4/r32/esp
 3173     (tailor-exit-descriptor %edx 0x10)
 3174     #
 3175     (write _test-input-stream "fn f {\n")
 3176     (write _test-input-stream "  var x: int\n")
 3177     (write _test-input-stream "  g x\n")
 3178     (write _test-input-stream "}\n")
 3179     (write _test-input-stream "fn g a: foo {\n")
 3180     (write _test-input-stream "}\n")
 3181     # convert
 3182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3183     # registers except esp clobbered at this point
 3184     # restore ed
 3185     89/<- %edx 4/r32/esp
 3186     (flush _test-output-buffered-file)
 3187     (flush _test-error-buffered-file)
 3188 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3194     # check output
 3195     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 3196     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-incorrect-inout-type: error message")
 3197     # check that stop(1) was called
 3198     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 3199     # don't restore from ebp
 3200     81 0/subop/add %esp 8/imm32
 3201     5d/pop-to-ebp
 3202     c3/return
 3203 
 3204 test-convert-function-call-with-inout-with-incorrect-compound-type:
 3205     # . prologue
 3206     55/push-ebp
 3207     89/<- %ebp 4/r32/esp
 3208     # setup
 3209     (clear-stream _test-input-stream)
 3210     (clear-stream $_test-input-buffered-file->buffer)
 3211     (clear-stream _test-output-stream)
 3212     (clear-stream $_test-output-buffered-file->buffer)
 3213     (clear-stream _test-error-stream)
 3214     (clear-stream $_test-error-buffered-file->buffer)
 3215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3216     68/push 0/imm32
 3217     68/push 0/imm32
 3218     89/<- %edx 4/r32/esp
 3219     (tailor-exit-descriptor %edx 0x10)
 3220     #
 3221     (write _test-input-stream "fn f {\n")
 3222     (write _test-input-stream "  var x: (addr int)\n")
 3223     (write _test-input-stream "  g x\n")
 3224     (write _test-input-stream "}\n")
 3225     (write _test-input-stream "fn g a: (addr bool) {\n")
 3226     (write _test-input-stream "}\n")
 3227     # convert
 3228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3229     # registers except esp clobbered at this point
 3230     # restore ed
 3231     89/<- %edx 4/r32/esp
 3232     (flush _test-output-buffered-file)
 3233     (flush _test-error-buffered-file)
 3234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3240     # check output
 3241     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 3242     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: error message")
 3243     # don't restore from ebp
 3244     81 0/subop/add %esp 8/imm32
 3245     # . epilogue
 3246     5d/pop-to-ebp
 3247     c3/return
 3248 
 3249 test-convert-function-call-with-inout-with-multiple-type-parameters:
 3250     # . prologue
 3251     55/push-ebp
 3252     89/<- %ebp 4/r32/esp
 3253     # setup
 3254     (clear-stream _test-input-stream)
 3255     (clear-stream $_test-input-buffered-file->buffer)
 3256     (clear-stream _test-output-stream)
 3257     (clear-stream $_test-output-buffered-file->buffer)
 3258     (clear-stream _test-error-stream)
 3259     (clear-stream $_test-error-buffered-file->buffer)
 3260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3261     68/push 0/imm32
 3262     68/push 0/imm32
 3263     89/<- %edx 4/r32/esp
 3264     (tailor-exit-descriptor %edx 0x10)
 3265     #
 3266     (write _test-input-stream "fn f {\n")
 3267     (write _test-input-stream "  var x: (addr int)\n")
 3268     (write _test-input-stream "  var y: (addr int)\n")
 3269     (write _test-input-stream "  g x, y\n")
 3270     (write _test-input-stream "}\n")
 3271     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3272     (write _test-input-stream "}\n")
 3273     # convert
 3274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3275     # registers except esp clobbered at this point
 3276     # restore ed
 3277     89/<- %edx 4/r32/esp
 3278     (flush _test-output-buffered-file)
 3279     (flush _test-error-buffered-file)
 3280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3286     # no errors
 3287     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3288     # don't bother checking the generated code
 3289     # don't restore from ebp
 3290     81 0/subop/add %esp 8/imm32
 3291     # . epilogue
 3292     5d/pop-to-ebp
 3293     c3/return
 3294 
 3295 test-type-parameter-matches-rest-of-type:
 3296     # . prologue
 3297     55/push-ebp
 3298     89/<- %ebp 4/r32/esp
 3299     # setup
 3300     (clear-stream _test-input-stream)
 3301     (clear-stream $_test-input-buffered-file->buffer)
 3302     (clear-stream _test-output-stream)
 3303     (clear-stream $_test-output-buffered-file->buffer)
 3304     (clear-stream _test-error-stream)
 3305     (clear-stream $_test-error-buffered-file->buffer)
 3306     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3307     68/push 0/imm32
 3308     68/push 0/imm32
 3309     89/<- %edx 4/r32/esp
 3310     (tailor-exit-descriptor %edx 0x10)
 3311     #
 3312     (write _test-input-stream "fn f {\n")
 3313     (write _test-input-stream "  var x: (addr array int)\n")
 3314     (write _test-input-stream "  g x\n")
 3315     (write _test-input-stream "}\n")
 3316     (write _test-input-stream "fn g a: (addr _) {\n")
 3317     (write _test-input-stream "}\n")
 3318     # convert
 3319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3320     # registers except esp clobbered at this point
 3321     # restore ed
 3322     89/<- %edx 4/r32/esp
 3323     (flush _test-output-buffered-file)
 3324     (flush _test-error-buffered-file)
 3325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3331     # no errors
 3332     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3333     # don't bother checking the generated code
 3334     # don't restore from ebp
 3335     81 0/subop/add %esp 8/imm32
 3336     # . epilogue
 3337     5d/pop-to-ebp
 3338     c3/return
 3339 
 3340 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3341     # . prologue
 3342     55/push-ebp
 3343     89/<- %ebp 4/r32/esp
 3344     # setup
 3345     (clear-stream _test-input-stream)
 3346     (clear-stream $_test-input-buffered-file->buffer)
 3347     (clear-stream _test-output-stream)
 3348     (clear-stream $_test-output-buffered-file->buffer)
 3349     (clear-stream _test-error-stream)
 3350     (clear-stream $_test-error-buffered-file->buffer)
 3351     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3352     68/push 0/imm32
 3353     68/push 0/imm32
 3354     89/<- %edx 4/r32/esp
 3355     (tailor-exit-descriptor %edx 0x10)
 3356     #
 3357     (write _test-input-stream "fn f {\n")
 3358     (write _test-input-stream "  var x: (addr int)\n")
 3359     (write _test-input-stream "  var y: (addr boolean)\n")
 3360     (write _test-input-stream "  g x, y\n")
 3361     (write _test-input-stream "}\n")
 3362     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3363     (write _test-input-stream "}\n")
 3364     # convert
 3365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3366     # registers except esp clobbered at this point
 3367     # restore ed
 3368     89/<- %edx 4/r32/esp
 3369     (flush _test-output-buffered-file)
 3370     (flush _test-error-buffered-file)
 3371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3377     # check output
 3378     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3379     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'y' is not right"  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: error message")
 3380     # don't restore from ebp
 3381     81 0/subop/add %esp 8/imm32
 3382     # . epilogue
 3383     5d/pop-to-ebp
 3384     c3/return
 3385 
 3386 test-convert-function-call-with-too-few-inouts:
 3387     # . prologue
 3388     55/push-ebp
 3389     89/<- %ebp 4/r32/esp
 3390     # setup
 3391     (clear-stream _test-input-stream)
 3392     (clear-stream $_test-input-buffered-file->buffer)
 3393     (clear-stream _test-output-stream)
 3394     (clear-stream $_test-output-buffered-file->buffer)
 3395     (clear-stream _test-error-stream)
 3396     (clear-stream $_test-error-buffered-file->buffer)
 3397     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3398     68/push 0/imm32
 3399     68/push 0/imm32
 3400     89/<- %edx 4/r32/esp
 3401     (tailor-exit-descriptor %edx 0x10)
 3402     #
 3403     (write _test-input-stream "fn f {\n")
 3404     (write _test-input-stream "  g\n")
 3405     (write _test-input-stream "}\n")
 3406     (write _test-input-stream "fn g a: int {\n")
 3407     (write _test-input-stream "}\n")
 3408     # convert
 3409     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3410     # registers except esp clobbered at this point
 3411     # restore ed
 3412     89/<- %edx 4/r32/esp
 3413     (flush _test-output-buffered-file)
 3414     (flush _test-error-buffered-file)
 3415 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3421     # check output
 3422     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3423     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few inouts"  "F - test-convert-function-call-with-too-few-inouts: error message")
 3424     # check that stop(1) was called
 3425     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3426     # don't restore from ebp
 3427     81 0/subop/add %esp 8/imm32
 3428     5d/pop-to-ebp
 3429     c3/return
 3430 
 3431 test-convert-function-call-with-too-many-inouts:
 3432     # . prologue
 3433     55/push-ebp
 3434     89/<- %ebp 4/r32/esp
 3435     # setup
 3436     (clear-stream _test-input-stream)
 3437     (clear-stream $_test-input-buffered-file->buffer)
 3438     (clear-stream _test-output-stream)
 3439     (clear-stream $_test-output-buffered-file->buffer)
 3440     (clear-stream _test-error-stream)
 3441     (clear-stream $_test-error-buffered-file->buffer)
 3442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3443     68/push 0/imm32
 3444     68/push 0/imm32
 3445     89/<- %edx 4/r32/esp
 3446     (tailor-exit-descriptor %edx 0x10)
 3447     #
 3448     (write _test-input-stream "fn f {\n")
 3449     (write _test-input-stream "  var x: int\n")
 3450     (write _test-input-stream "  g x\n")
 3451     (write _test-input-stream "}\n")
 3452     (write _test-input-stream "fn g {\n")
 3453     (write _test-input-stream "}\n")
 3454     # convert
 3455     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3456     # registers except esp clobbered at this point
 3457     # restore ed
 3458     89/<- %edx 4/r32/esp
 3459     (flush _test-output-buffered-file)
 3460     (flush _test-error-buffered-file)
 3461 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3467     # check output
 3468     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3469     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many inouts"  "F - test-convert-function-call-with-too-many-inouts: error message")
 3470     # check that stop(1) was called
 3471     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3472     # don't restore from ebp
 3473     81 0/subop/add %esp 8/imm32
 3474     5d/pop-to-ebp
 3475     c3/return
 3476 
 3477 test-convert-function-call-with-incorrect-output-type:
 3478     # . prologue
 3479     55/push-ebp
 3480     89/<- %ebp 4/r32/esp
 3481     # setup
 3482     (clear-stream _test-input-stream)
 3483     (clear-stream $_test-input-buffered-file->buffer)
 3484     (clear-stream _test-output-stream)
 3485     (clear-stream $_test-output-buffered-file->buffer)
 3486     (clear-stream _test-error-stream)
 3487     (clear-stream $_test-error-buffered-file->buffer)
 3488     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3489     68/push 0/imm32
 3490     68/push 0/imm32
 3491     89/<- %edx 4/r32/esp
 3492     (tailor-exit-descriptor %edx 0x10)
 3493     #
 3494     (write _test-input-stream "fn f {\n")
 3495     (write _test-input-stream "  var x/eax: int <- g\n")
 3496     (write _test-input-stream "}\n")
 3497     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3498     (write _test-input-stream "}\n")
 3499     # convert
 3500     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3501     # registers except esp clobbered at this point
 3502     # restore ed
 3503     89/<- %edx 4/r32/esp
 3504     (flush _test-output-buffered-file)
 3505     (flush _test-error-buffered-file)
 3506 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3512     # check output
 3513     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3514     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-type: error message")
 3515     # check that stop(1) was called
 3516     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3517     # don't restore from ebp
 3518     81 0/subop/add %esp 8/imm32
 3519     5d/pop-to-ebp
 3520     c3/return
 3521 
 3522 test-convert-function-call-with-too-few-outputs:
 3523     # . prologue
 3524     55/push-ebp
 3525     89/<- %ebp 4/r32/esp
 3526     # setup
 3527     (clear-stream _test-input-stream)
 3528     (clear-stream $_test-input-buffered-file->buffer)
 3529     (clear-stream _test-output-stream)
 3530     (clear-stream $_test-output-buffered-file->buffer)
 3531     (clear-stream _test-error-stream)
 3532     (clear-stream $_test-error-buffered-file->buffer)
 3533     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3534     68/push 0/imm32
 3535     68/push 0/imm32
 3536     89/<- %edx 4/r32/esp
 3537     (tailor-exit-descriptor %edx 0x10)
 3538     #
 3539     (write _test-input-stream "fn f {\n")
 3540     (write _test-input-stream "  g\n")
 3541     (write _test-input-stream "}\n")
 3542     (write _test-input-stream "fn g -> _/eax: int {\n")
 3543     (write _test-input-stream "}\n")
 3544     # convert
 3545     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3546     # registers except esp clobbered at this point
 3547     # restore ed
 3548     89/<- %edx 4/r32/esp
 3549     (flush _test-output-buffered-file)
 3550     (flush _test-error-buffered-file)
 3551 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3557     # check output
 3558     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3559     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few outputs"  "F - test-convert-function-call-with-too-few-outputs: error message")
 3560     # check that stop(1) was called
 3561     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3562     # don't restore from ebp
 3563     81 0/subop/add %esp 8/imm32
 3564     5d/pop-to-ebp
 3565     c3/return
 3566 
 3567 test-convert-function-call-with-too-many-outputs:
 3568     # . prologue
 3569     55/push-ebp
 3570     89/<- %ebp 4/r32/esp
 3571     # setup
 3572     (clear-stream _test-input-stream)
 3573     (clear-stream $_test-input-buffered-file->buffer)
 3574     (clear-stream _test-output-stream)
 3575     (clear-stream $_test-output-buffered-file->buffer)
 3576     (clear-stream _test-error-stream)
 3577     (clear-stream $_test-error-buffered-file->buffer)
 3578     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3579     68/push 0/imm32
 3580     68/push 0/imm32
 3581     89/<- %edx 4/r32/esp
 3582     (tailor-exit-descriptor %edx 0x10)
 3583     #
 3584     (write _test-input-stream "fn f {\n")
 3585     (write _test-input-stream "  var x/eax: int <- g\n")
 3586     (write _test-input-stream "}\n")
 3587     (write _test-input-stream "fn g {\n")
 3588     (write _test-input-stream "}\n")
 3589     # convert
 3590     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3591     # registers except esp clobbered at this point
 3592     # restore ed
 3593     89/<- %edx 4/r32/esp
 3594     (flush _test-output-buffered-file)
 3595     (flush _test-error-buffered-file)
 3596 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3602     # check output
 3603     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3604     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many outputs"  "F - test-convert-function-call-with-too-many-outputs: error message")
 3605     # check that stop(1) was called
 3606     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3607     # don't restore from ebp
 3608     81 0/subop/add %esp 8/imm32
 3609     5d/pop-to-ebp
 3610     c3/return
 3611 
 3612 test-convert-function-call-with-missing-output-register:
 3613     # . prologue
 3614     55/push-ebp
 3615     89/<- %ebp 4/r32/esp
 3616     # setup
 3617     (clear-stream _test-input-stream)
 3618     (clear-stream $_test-input-buffered-file->buffer)
 3619     (clear-stream _test-output-stream)
 3620     (clear-stream $_test-output-buffered-file->buffer)
 3621     (clear-stream _test-error-stream)
 3622     (clear-stream $_test-error-buffered-file->buffer)
 3623     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3624     68/push 0/imm32
 3625     68/push 0/imm32
 3626     89/<- %edx 4/r32/esp
 3627     (tailor-exit-descriptor %edx 0x10)
 3628     #
 3629     (write _test-input-stream "fn f {\n")
 3630     (write _test-input-stream "  var x: int\n")
 3631     (write _test-input-stream "  x <- g\n")
 3632     (write _test-input-stream "}\n")
 3633     (write _test-input-stream "fn g -> _/eax: int {\n")
 3634     (write _test-input-stream "}\n")
 3635     # convert
 3636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3637     # registers except esp clobbered at this point
 3638     # restore ed
 3639     89/<- %edx 4/r32/esp
 3640     (flush _test-output-buffered-file)
 3641     (flush _test-error-buffered-file)
 3642 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3648     # check output
 3649     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3650     (check-next-stream-line-equal _test-error-stream  "fn f: call g: output 'x' is not in a register"  "F - test-convert-function-call-with-missing-output-register: error message")
 3651     # check that stop(1) was called
 3652     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3653     # don't restore from ebp
 3654     81 0/subop/add %esp 8/imm32
 3655     5d/pop-to-ebp
 3656     c3/return
 3657 
 3658 test-convert-function-call-with-incorrect-output-register:
 3659     # . prologue
 3660     55/push-ebp
 3661     89/<- %ebp 4/r32/esp
 3662     # setup
 3663     (clear-stream _test-input-stream)
 3664     (clear-stream $_test-input-buffered-file->buffer)
 3665     (clear-stream _test-output-stream)
 3666     (clear-stream $_test-output-buffered-file->buffer)
 3667     (clear-stream _test-error-stream)
 3668     (clear-stream $_test-error-buffered-file->buffer)
 3669     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3670     68/push 0/imm32
 3671     68/push 0/imm32
 3672     89/<- %edx 4/r32/esp
 3673     (tailor-exit-descriptor %edx 0x10)
 3674     #
 3675     (write _test-input-stream "fn f {\n")
 3676     (write _test-input-stream "  var x/ecx: int <- g\n")
 3677     (write _test-input-stream "}\n")
 3678     (write _test-input-stream "fn g -> _/eax: int {\n")
 3679     (write _test-input-stream "}\n")
 3680     # convert
 3681     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3682     # registers except esp clobbered at this point
 3683     # restore ed
 3684     89/<- %edx 4/r32/esp
 3685     (flush _test-output-buffered-file)
 3686     (flush _test-error-buffered-file)
 3687 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3693     # check output
 3694     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3695     (check-next-stream-line-equal _test-error-stream  "fn f: call g: register for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-register: error message")
 3696     # check that stop(1) was called
 3697     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3698     # don't restore from ebp
 3699     81 0/subop/add %esp 8/imm32
 3700     5d/pop-to-ebp
 3701     c3/return
 3702 
 3703 test-convert-function-with-local-var-dereferenced:
 3704     # . prologue
 3705     55/push-ebp
 3706     89/<- %ebp 4/r32/esp
 3707     # setup
 3708     (clear-stream _test-input-stream)
 3709     (clear-stream $_test-input-buffered-file->buffer)
 3710     (clear-stream _test-output-stream)
 3711     (clear-stream $_test-output-buffered-file->buffer)
 3712     #
 3713     (write _test-input-stream "fn foo {\n")
 3714     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3715     (write _test-input-stream "  increment *x\n")
 3716     (write _test-input-stream "}\n")
 3717     # convert
 3718     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3719     (flush _test-output-buffered-file)
 3720 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3726     # check output
 3727     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3728     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3729     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3730     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3731     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3732     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3733     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3734     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3735     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3736     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3737     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3738     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3739     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3740     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3741     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3742     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3743     # . epilogue
 3744     89/<- %esp 5/r32/ebp
 3745     5d/pop-to-ebp
 3746     c3/return
 3747 
 3748 test-dereference-of-var-on-stack:
 3749     # . prologue
 3750     55/push-ebp
 3751     89/<- %ebp 4/r32/esp
 3752     # setup
 3753     (clear-stream _test-input-stream)
 3754     (clear-stream $_test-input-buffered-file->buffer)
 3755     (clear-stream _test-output-stream)
 3756     (clear-stream $_test-output-buffered-file->buffer)
 3757     (clear-stream _test-error-stream)
 3758     (clear-stream $_test-error-buffered-file->buffer)
 3759     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3760     68/push 0/imm32
 3761     68/push 0/imm32
 3762     89/<- %edx 4/r32/esp
 3763     (tailor-exit-descriptor %edx 0x10)
 3764     #
 3765     (write _test-input-stream "fn foo {\n")
 3766     (write _test-input-stream "  var x: (addr int)\n")
 3767     (write _test-input-stream "  increment *x\n")
 3768     (write _test-input-stream "}\n")
 3769     # convert
 3770     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3771     # registers except esp clobbered at this point
 3772     # restore ed
 3773     89/<- %edx 4/r32/esp
 3774     (flush _test-output-buffered-file)
 3775     (flush _test-error-buffered-file)
 3776 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3782     # check output
 3783     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3784     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
 3785     # check that stop(1) was called
 3786     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3787     # don't restore from ebp
 3788     81 0/subop/add %esp 8/imm32
 3789     # . epilogue
 3790     5d/pop-to-ebp
 3791     c3/return
 3792 
 3793 test-convert-function-with-byte-operations:
 3794     # . prologue
 3795     55/push-ebp
 3796     89/<- %ebp 4/r32/esp
 3797     # setup
 3798     (clear-stream _test-input-stream)
 3799     (clear-stream $_test-input-buffered-file->buffer)
 3800     (clear-stream _test-output-stream)
 3801     (clear-stream $_test-output-buffered-file->buffer)
 3802     #
 3803     (write _test-input-stream "fn foo {\n")
 3804     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3805     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3806     (write _test-input-stream "  y <- copy-byte x\n")
 3807     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3808     (write _test-input-stream "  y <- copy-byte *z\n")
 3809     (write _test-input-stream "  copy-byte-to *z, x\n")
 3810     (write _test-input-stream "}\n")
 3811     # convert
 3812     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3813     (flush _test-output-buffered-file)
 3814 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3820     # check output
 3821     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3822     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3823     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3824     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3825     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3828     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3829     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3830     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3831     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3832     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
 3833     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
 3834     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
 3835     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
 3836     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
 3837     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
 3838     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
 3839     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
 3840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
 3841     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
 3842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
 3843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
 3844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
 3845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
 3846     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
 3847     # . epilogue
 3848     89/<- %esp 5/r32/ebp
 3849     5d/pop-to-ebp
 3850     c3/return
 3851 
 3852 # variables of type 'byte' are not allowed on the stack
 3853 test-byte-values-on-stack:
 3854     # . prologue
 3855     55/push-ebp
 3856     89/<- %ebp 4/r32/esp
 3857     # setup
 3858     (clear-stream _test-input-stream)
 3859     (clear-stream $_test-input-buffered-file->buffer)
 3860     (clear-stream _test-output-stream)
 3861     (clear-stream $_test-output-buffered-file->buffer)
 3862     (clear-stream _test-error-stream)
 3863     (clear-stream $_test-error-buffered-file->buffer)
 3864     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3865     68/push 0/imm32
 3866     68/push 0/imm32
 3867     89/<- %edx 4/r32/esp
 3868     (tailor-exit-descriptor %edx 0x10)
 3869     #
 3870     (write _test-input-stream "fn foo {\n")
 3871     (write _test-input-stream "  var x: byte\n")
 3872     (write _test-input-stream "}\n")
 3873     # convert
 3874     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3875     # registers except esp clobbered at this point
 3876     # restore ed
 3877     89/<- %edx 4/r32/esp
 3878     (flush _test-output-buffered-file)
 3879     (flush _test-error-buffered-file)
 3880 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3886     # check output
 3887     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3888     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
 3889     # check that stop(1) was called
 3890     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3891     # don't restore from ebp
 3892     81 0/subop/add %esp 8/imm32
 3893     # . epilogue
 3894     5d/pop-to-ebp
 3895     c3/return
 3896 
 3897 # variables of type 'byte' are not allowed in esi or edi
 3898 test-byte-values-in-unsupported-registers:
 3899     # . prologue
 3900     55/push-ebp
 3901     89/<- %ebp 4/r32/esp
 3902     # setup
 3903     (clear-stream _test-input-stream)
 3904     (clear-stream $_test-input-buffered-file->buffer)
 3905     (clear-stream _test-output-stream)
 3906     (clear-stream $_test-output-buffered-file->buffer)
 3907     (clear-stream _test-error-stream)
 3908     (clear-stream $_test-error-buffered-file->buffer)
 3909     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3910     68/push 0/imm32
 3911     68/push 0/imm32
 3912     89/<- %edx 4/r32/esp
 3913     (tailor-exit-descriptor %edx 0x10)
 3914     #
 3915     (write _test-input-stream "fn foo {\n")
 3916     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3917     (write _test-input-stream "}\n")
 3918     # convert
 3919     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3920     # registers except esp clobbered at this point
 3921     # restore ed
 3922     89/<- %edx 4/r32/esp
 3923     (flush _test-output-buffered-file)
 3924     (flush _test-error-buffered-file)
 3925 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3931     # check output
 3932     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3933     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
 3934     # check that stop(1) was called
 3935     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3936     # don't restore from ebp
 3937     81 0/subop/add %esp 8/imm32
 3938     # . epilogue
 3939     5d/pop-to-ebp
 3940     c3/return
 3941 
 3942 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3943 test-copy-byte-var-from-fn-arg:
 3944     # . prologue
 3945     55/push-ebp
 3946     89/<- %ebp 4/r32/esp
 3947     # setup
 3948     (clear-stream _test-input-stream)
 3949     (clear-stream $_test-input-buffered-file->buffer)
 3950     (clear-stream _test-output-stream)
 3951     (clear-stream $_test-output-buffered-file->buffer)
 3952     #
 3953     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3954     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3955     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3956     (write _test-input-stream "}\n")
 3957     # convert
 3958     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3959     (flush _test-output-buffered-file)
 3960 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3966     # check output
 3967     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3968     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3969     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3970     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3971     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3973     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3974     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3975     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3976     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3977     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3978     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3979     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3980     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3981     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3982     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3983     # . epilogue
 3984     89/<- %esp 5/r32/ebp
 3985     5d/pop-to-ebp
 3986     c3/return
 3987 
 3988 test-convert-compare-register-with-literal:
 3989     # . prologue
 3990     55/push-ebp
 3991     89/<- %ebp 4/r32/esp
 3992     # setup
 3993     (clear-stream _test-input-stream)
 3994     (clear-stream $_test-input-buffered-file->buffer)
 3995     (clear-stream _test-output-stream)
 3996     (clear-stream $_test-output-buffered-file->buffer)
 3997     #
 3998     (write _test-input-stream "fn foo {\n")
 3999     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 4000     (write _test-input-stream "  compare x, 0\n")
 4001     (write _test-input-stream "}\n")
 4002     # convert
 4003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4004     (flush _test-output-buffered-file)
 4005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 4013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 4014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 4015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 4016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 4017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 4018     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4019     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 4020     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 4021     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4022     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 4023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 4024     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 4025     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 4026     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 4027     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 4028     # . epilogue
 4029     89/<- %esp 5/r32/ebp
 4030     5d/pop-to-ebp
 4031     c3/return
 4032 
 4033 test-convert-compare-byte-with-literal:
 4034     # . prologue
 4035     55/push-ebp
 4036     89/<- %ebp 4/r32/esp
 4037     # setup
 4038     (clear-stream _test-input-stream)
 4039     (clear-stream $_test-input-buffered-file->buffer)
 4040     (clear-stream _test-output-stream)
 4041     (clear-stream $_test-output-buffered-file->buffer)
 4042     #
 4043     (write _test-input-stream "fn foo {\n")
 4044     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
 4045     (write _test-input-stream "  compare x, 0\n")
 4046     (write _test-input-stream "}\n")
 4047     # convert
 4048     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4049     (flush _test-output-buffered-file)
 4050 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4056     # no errors; output is identical to test-convert-compare-register-with-literal
 4057     # . epilogue
 4058     89/<- %esp 5/r32/ebp
 4059     5d/pop-to-ebp
 4060     c3/return
 4061 
 4062 test-unknown-variable:
 4063     # . prologue
 4064     55/push-ebp
 4065     89/<- %ebp 4/r32/esp
 4066     # setup
 4067     (clear-stream _test-input-stream)
 4068     (clear-stream $_test-input-buffered-file->buffer)
 4069     (clear-stream _test-output-stream)
 4070     (clear-stream $_test-output-buffered-file->buffer)
 4071     (clear-stream _test-error-stream)
 4072     (clear-stream $_test-error-buffered-file->buffer)
 4073     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4074     68/push 0/imm32
 4075     68/push 0/imm32
 4076     89/<- %edx 4/r32/esp
 4077     (tailor-exit-descriptor %edx 0x10)
 4078     #
 4079     (write _test-input-stream "fn foo {\n")
 4080     (write _test-input-stream "  compare x, 0\n")
 4081     (write _test-input-stream "}\n")
 4082     # convert
 4083     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4084     # registers except esp clobbered at this point
 4085     # restore ed
 4086     89/<- %edx 4/r32/esp
 4087     (flush _test-output-buffered-file)
 4088     (flush _test-error-buffered-file)
 4089 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4095     # check output
 4096     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 4097     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 4098     # check that stop(1) was called
 4099     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 4100     # don't restore from ebp
 4101     81 0/subop/add %esp 8/imm32
 4102     # . epilogue
 4103     5d/pop-to-ebp
 4104     c3/return
 4105 
 4106 test-convert-function-with-local-var-in-block:
 4107     # . prologue
 4108     55/push-ebp
 4109     89/<- %ebp 4/r32/esp
 4110     # setup
 4111     (clear-stream _test-input-stream)
 4112     (clear-stream $_test-input-buffered-file->buffer)
 4113     (clear-stream _test-output-stream)
 4114     (clear-stream $_test-output-buffered-file->buffer)
 4115     #
 4116     (write _test-input-stream "fn foo {\n")
 4117     (write _test-input-stream "  {\n")
 4118     (write _test-input-stream "    var x: int\n")
 4119     (write _test-input-stream "    increment x\n")
 4120     (write _test-input-stream "  }\n")
 4121     (write _test-input-stream "}\n")
 4122     # convert
 4123     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4124     (flush _test-output-buffered-file)
 4125 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4131     # check output
 4132     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 4133     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 4134     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 4135     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 4136     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 4137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 4138     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 4139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 4140     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 4141     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 4142     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-block/10")
 4143     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 4144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 4145     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 4146     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 4147     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 4148     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 4149     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 4150     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 4151     # . epilogue
 4152     89/<- %esp 5/r32/ebp
 4153     5d/pop-to-ebp
 4154     c3/return
 4155 
 4156 test-convert-function-with-local-var-in-mem-after-block:
 4157     # . prologue
 4158     55/push-ebp
 4159     89/<- %ebp 4/r32/esp
 4160     # setup
 4161     (clear-stream _test-input-stream)
 4162     (clear-stream $_test-input-buffered-file->buffer)
 4163     (clear-stream _test-output-stream)
 4164     (clear-stream $_test-output-buffered-file->buffer)
 4165     #
 4166     (write _test-input-stream "fn foo {\n")
 4167     (write _test-input-stream "  {\n")
 4168     (write _test-input-stream "    var y: int\n")
 4169     (write _test-input-stream "  }\n")
 4170     (write _test-input-stream "  var x: int\n")
 4171     (write _test-input-stream "  increment x\n")
 4172     (write _test-input-stream "}\n")
 4173     # convert
 4174     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4175     (flush _test-output-buffered-file)
 4176 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4182     # check output
 4183     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 4184     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 4185     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 4186     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem-after-block/3")
 4187     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 4188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 4189     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 4190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 4191     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 4192     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/9")
 4193     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 4194     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 4195     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 4196     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem-after-block/13")
 4197     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/14")
 4198     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 4199     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 4200     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 4201     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem-after-block/18")
 4202     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 4203     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 4204     # . epilogue
 4205     89/<- %esp 5/r32/ebp
 4206     5d/pop-to-ebp
 4207     c3/return
 4208 
 4209 test-convert-function-with-local-var-in-named-block:
 4210     # . prologue
 4211     55/push-ebp
 4212     89/<- %ebp 4/r32/esp
 4213     # setup
 4214     (clear-stream _test-input-stream)
 4215     (clear-stream $_test-input-buffered-file->buffer)
 4216     (clear-stream _test-output-stream)
 4217     (clear-stream $_test-output-buffered-file->buffer)
 4218     #
 4219     (write _test-input-stream "fn foo {\n")
 4220     (write _test-input-stream "  $bar: {\n")
 4221     (write _test-input-stream "    var x: int\n")
 4222     (write _test-input-stream "    increment x\n")
 4223     (write _test-input-stream "  }\n")
 4224     (write _test-input-stream "}\n")
 4225     # convert
 4226     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4227     (flush _test-output-buffered-file)
 4228 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4234     # check output
 4235     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 4236     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 4237     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 4238     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 4239     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 4240     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 4241     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 4242     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 4243     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 4244     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-named-block/9")
 4245     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-named-block/10")
 4246     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 4247     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 4248     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 4249     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 4250     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 4251     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 4252     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 4253     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 4254     # . epilogue
 4255     89/<- %esp 5/r32/ebp
 4256     5d/pop-to-ebp
 4257     c3/return
 4258 
 4259 test-unknown-variable-in-named-block:
 4260     # . prologue
 4261     55/push-ebp
 4262     89/<- %ebp 4/r32/esp
 4263     # setup
 4264     (clear-stream _test-input-stream)
 4265     (clear-stream $_test-input-buffered-file->buffer)
 4266     (clear-stream _test-output-stream)
 4267     (clear-stream $_test-output-buffered-file->buffer)
 4268     (clear-stream _test-error-stream)
 4269     (clear-stream $_test-error-buffered-file->buffer)
 4270     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4271     68/push 0/imm32
 4272     68/push 0/imm32
 4273     89/<- %edx 4/r32/esp
 4274     (tailor-exit-descriptor %edx 0x10)
 4275     #
 4276     (write _test-input-stream "fn foo {\n")
 4277     (write _test-input-stream "  $a: {\n")
 4278     (write _test-input-stream "    compare x, 0\n")
 4279     (write _test-input-stream "  }\n")
 4280     (write _test-input-stream "}\n")
 4281     # convert
 4282     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4283     # registers except esp clobbered at this point
 4284     # restore ed
 4285     89/<- %edx 4/r32/esp
 4286     (flush _test-output-buffered-file)
 4287     (flush _test-error-buffered-file)
 4288 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4294     # check output
 4295     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4296     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4297     # check that stop(1) was called
 4298     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4299     # don't restore from ebp
 4300     81 0/subop/add %esp 8/imm32
 4301     # . epilogue
 4302     5d/pop-to-ebp
 4303     c3/return
 4304 
 4305 test-always-shadow-outermost-reg-vars-in-function:
 4306     # . prologue
 4307     55/push-ebp
 4308     89/<- %ebp 4/r32/esp
 4309     # setup
 4310     (clear-stream _test-input-stream)
 4311     (clear-stream $_test-input-buffered-file->buffer)
 4312     (clear-stream _test-output-stream)
 4313     (clear-stream $_test-output-buffered-file->buffer)
 4314     #
 4315     (write _test-input-stream "fn foo {\n")
 4316     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4317     (write _test-input-stream "}\n")
 4318     # convert
 4319     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4320     (flush _test-output-buffered-file)
 4321 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4327     # check output
 4328     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4329     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4330     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4331     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4332     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4333     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4334     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4335     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4336     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4337     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4338     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4339     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4340     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4341     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4342     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4343     # . epilogue
 4344     89/<- %esp 5/r32/ebp
 4345     5d/pop-to-ebp
 4346     c3/return
 4347 
 4348 test-shadow-local:
 4349     # . prologue
 4350     55/push-ebp
 4351     89/<- %ebp 4/r32/esp
 4352     # setup
 4353     (clear-stream _test-input-stream)
 4354     (clear-stream $_test-input-buffered-file->buffer)
 4355     (clear-stream _test-output-stream)
 4356     (clear-stream $_test-output-buffered-file->buffer)
 4357     #
 4358     (write _test-input-stream "fn foo {\n")
 4359     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4360     (write _test-input-stream "  {\n")
 4361     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4362     (write _test-input-stream "  }\n")
 4363     (write _test-input-stream "  x <- increment\n")
 4364     (write _test-input-stream "}\n")
 4365     # convert
 4366     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4367     (flush _test-output-buffered-file)
 4368 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4374     # check output
 4375     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4376     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4377     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4378     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4379     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4380     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4381     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4382     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4383     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4384     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4385     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4386     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4387     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4388     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4390     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4391     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4392     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4393     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4394     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4395     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4396     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4397     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4398     # . epilogue
 4399     89/<- %esp 5/r32/ebp
 4400     5d/pop-to-ebp
 4401     c3/return
 4402 
 4403 test-shadow-name:
 4404     # . prologue
 4405     55/push-ebp
 4406     89/<- %ebp 4/r32/esp
 4407     # setup
 4408     (clear-stream _test-input-stream)
 4409     (clear-stream $_test-input-buffered-file->buffer)
 4410     (clear-stream _test-output-stream)
 4411     (clear-stream $_test-output-buffered-file->buffer)
 4412     #
 4413     (write _test-input-stream "fn foo {\n")
 4414     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4415     (write _test-input-stream "  {\n")
 4416     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4417     (write _test-input-stream "  }\n")
 4418     (write _test-input-stream "  x <- increment\n")
 4419     (write _test-input-stream "}\n")
 4420     # convert
 4421     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4422     (flush _test-output-buffered-file)
 4423 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4429     # check output
 4430     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4431     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4432     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4433     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4434     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4435     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4436     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4437     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4438     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4439     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4440     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4441     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4442     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4443     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4445     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4446     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4447     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4448     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4449     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4450     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4451     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4452     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4453     # . epilogue
 4454     89/<- %esp 5/r32/ebp
 4455     5d/pop-to-ebp
 4456     c3/return
 4457 
 4458 test-shadow-name-2:
 4459     # . prologue
 4460     55/push-ebp
 4461     89/<- %ebp 4/r32/esp
 4462     # setup
 4463     (clear-stream _test-input-stream)
 4464     (clear-stream $_test-input-buffered-file->buffer)
 4465     (clear-stream _test-output-stream)
 4466     (clear-stream $_test-output-buffered-file->buffer)
 4467     #
 4468     (write _test-input-stream "fn foo {\n")
 4469     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4470     (write _test-input-stream "  {\n")
 4471     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4472     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4473     (write _test-input-stream "  }\n")
 4474     (write _test-input-stream "  x <- increment\n")
 4475     (write _test-input-stream "}\n")
 4476     # convert
 4477     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4478     (flush _test-output-buffered-file)
 4479 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4485     # check output
 4486     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4487     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4488     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4489     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4490     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4492     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4493     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4494     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4495     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4496     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4497     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4498     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4499     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4500     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4501     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4502     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4503     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4504     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4505     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4506     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4507     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4508     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4509     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4510     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4511     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4512     # . epilogue
 4513     89/<- %esp 5/r32/ebp
 4514     5d/pop-to-ebp
 4515     c3/return
 4516 
 4517 test-do-not-spill-same-register-in-block:
 4518     # . prologue
 4519     55/push-ebp
 4520     89/<- %ebp 4/r32/esp
 4521     # setup
 4522     (clear-stream _test-input-stream)
 4523     (clear-stream $_test-input-buffered-file->buffer)
 4524     (clear-stream _test-output-stream)
 4525     (clear-stream $_test-output-buffered-file->buffer)
 4526     #
 4527     (write _test-input-stream "fn foo {\n")
 4528     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4529     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4530     (write _test-input-stream "  y <- increment\n")
 4531     (write _test-input-stream "}\n")
 4532     # convert
 4533     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4534     (flush _test-output-buffered-file)
 4535 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4541     # check output
 4542     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4543     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4544     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4545     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4546     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4548     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4549     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4550     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4551     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4552     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4553     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4554     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4555     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4556     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4557     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4558     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4559     # . epilogue
 4560     89/<- %esp 5/r32/ebp
 4561     5d/pop-to-ebp
 4562     c3/return
 4563 
 4564 test-spill-different-register-in-block:
 4565     # . prologue
 4566     55/push-ebp
 4567     89/<- %ebp 4/r32/esp
 4568     # setup
 4569     (clear-stream _test-input-stream)
 4570     (clear-stream $_test-input-buffered-file->buffer)
 4571     (clear-stream _test-output-stream)
 4572     (clear-stream $_test-output-buffered-file->buffer)
 4573     #
 4574     (write _test-input-stream "fn foo {\n")
 4575     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4576     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4577     (write _test-input-stream "  y <- increment\n")
 4578     (write _test-input-stream "}\n")
 4579     # convert
 4580     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4581     (flush _test-output-buffered-file)
 4582 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4588     # check output
 4589     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4590     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4591     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4592     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4593     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4594     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4596     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4597     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4598     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4599     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4600     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4601     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4602     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4603     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4604     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4605     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4606     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4607     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4608     # . epilogue
 4609     89/<- %esp 5/r32/ebp
 4610     5d/pop-to-ebp
 4611     c3/return
 4612 
 4613 test-convert-function-with-branches-in-block:
 4614     # . prologue
 4615     55/push-ebp
 4616     89/<- %ebp 4/r32/esp
 4617     # setup
 4618     (clear-stream _test-input-stream)
 4619     (clear-stream $_test-input-buffered-file->buffer)
 4620     (clear-stream _test-output-stream)
 4621     (clear-stream $_test-output-buffered-file->buffer)
 4622     #
 4623     (write _test-input-stream "fn foo x: int {\n")
 4624     (write _test-input-stream "  {\n")
 4625     (write _test-input-stream "    break-if->=\n")
 4626     (write _test-input-stream "    loop-if-addr<\n")
 4627     (write _test-input-stream "    increment x\n")
 4628     (write _test-input-stream "    loop\n")
 4629     (write _test-input-stream "  }\n")
 4630     (write _test-input-stream "}\n")
 4631     # convert
 4632     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4633     (flush _test-output-buffered-file)
 4634 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4640     # check output
 4641     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4642     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4643     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4644     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4645     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4646     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4647     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4648     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4649     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4650     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4651     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4652     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4653     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4654     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4655     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4656     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4657     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4658     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4659     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4661     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4662     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4667     # . epilogue
 4668     89/<- %esp 5/r32/ebp
 4669     5d/pop-to-ebp
 4670     c3/return
 4671 
 4672 test-convert-function-with-branches-in-block-2:
 4673     # . prologue
 4674     55/push-ebp
 4675     89/<- %ebp 4/r32/esp
 4676     # setup
 4677     (clear-stream _test-input-stream)
 4678     (clear-stream $_test-input-buffered-file->buffer)
 4679     (clear-stream _test-output-stream)
 4680     (clear-stream $_test-output-buffered-file->buffer)
 4681     #
 4682     (write _test-input-stream "fn foo x: int {\n")
 4683     (write _test-input-stream "  {\n")
 4684     (write _test-input-stream "    break-if->=\n")
 4685     (write _test-input-stream "    loop-if-float<\n")
 4686     (write _test-input-stream "    increment x\n")
 4687     (write _test-input-stream "    loop\n")
 4688     (write _test-input-stream "  }\n")
 4689     (write _test-input-stream "}\n")
 4690     # convert
 4691     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4692     (flush _test-output-buffered-file)
 4693 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4699     # check output
 4700     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4701     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4702     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4703     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4704     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4706     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4707     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4708     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4709     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4710     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4711     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4712     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4713     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4714     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4715     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4716     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4717     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4718     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4720     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4721     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4722     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4723     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4724     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4725     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4726     # . epilogue
 4727     89/<- %esp 5/r32/ebp
 4728     5d/pop-to-ebp
 4729     c3/return
 4730 
 4731 test-convert-function-with-branches-in-named-block:
 4732     # . prologue
 4733     55/push-ebp
 4734     89/<- %ebp 4/r32/esp
 4735     # setup
 4736     (clear-stream _test-input-stream)
 4737     (clear-stream $_test-input-buffered-file->buffer)
 4738     (clear-stream _test-output-stream)
 4739     (clear-stream $_test-output-buffered-file->buffer)
 4740     #
 4741     (write _test-input-stream "fn foo x: int {\n")
 4742     (write _test-input-stream "  $bar: {\n")
 4743     (write _test-input-stream "    break-if->= $bar\n")
 4744     (write _test-input-stream "    loop-if-addr< $bar\n")
 4745     (write _test-input-stream "    increment x\n")
 4746     (write _test-input-stream "    loop\n")
 4747     (write _test-input-stream "  }\n")
 4748     (write _test-input-stream "}\n")
 4749     # convert
 4750     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4751     (flush _test-output-buffered-file)
 4752 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4758     # check output
 4759     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4760     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4761     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4762     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4763     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4764     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4765     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4766     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4767     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4768     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4769     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4770     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4771     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4772     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-named-block/13")
 4773     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4774     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4775     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4776     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4777     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4778     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4785     # . epilogue
 4786     89/<- %esp 5/r32/ebp
 4787     5d/pop-to-ebp
 4788     c3/return
 4789 
 4790 test-convert-function-with-var-in-nested-block:
 4791     # . prologue
 4792     55/push-ebp
 4793     89/<- %ebp 4/r32/esp
 4794     # setup
 4795     (clear-stream _test-input-stream)
 4796     (clear-stream $_test-input-buffered-file->buffer)
 4797     (clear-stream _test-output-stream)
 4798     (clear-stream $_test-output-buffered-file->buffer)
 4799     #
 4800     (write _test-input-stream "fn foo x: int {\n")
 4801     (write _test-input-stream "  {\n")
 4802     (write _test-input-stream "    {\n")
 4803     (write _test-input-stream "      var x: int\n")
 4804     (write _test-input-stream "      increment x\n")
 4805     (write _test-input-stream "    }\n")
 4806     (write _test-input-stream "  }\n")
 4807     (write _test-input-stream "}\n")
 4808     # convert
 4809     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4810     (flush _test-output-buffered-file)
 4811 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4817     # check output
 4818     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4819     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4821     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4822     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4824     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4826     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4827     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4828     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4829     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4830     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-var-in-nested-block/12")
 4831     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4833     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4835     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4837     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4838     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4839     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4840     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4841     # . epilogue
 4842     89/<- %esp 5/r32/ebp
 4843     5d/pop-to-ebp
 4844     c3/return
 4845 
 4846 test-convert-function-with-multiple-vars-in-nested-blocks:
 4847     # . prologue
 4848     55/push-ebp
 4849     89/<- %ebp 4/r32/esp
 4850     # setup
 4851     (clear-stream _test-input-stream)
 4852     (clear-stream $_test-input-buffered-file->buffer)
 4853     (clear-stream _test-output-stream)
 4854     (clear-stream $_test-output-buffered-file->buffer)
 4855     #
 4856     (write _test-input-stream "fn foo x: int {\n")
 4857     (write _test-input-stream "  {\n")
 4858     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4859     (write _test-input-stream "    {\n")
 4860     (write _test-input-stream "      var y: int\n")
 4861     (write _test-input-stream "      x <- add y\n")
 4862     (write _test-input-stream "    }\n")
 4863     (write _test-input-stream "  }\n")
 4864     (write _test-input-stream "}\n")
 4865     # convert
 4866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4867     (flush _test-output-buffered-file)
 4868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4874     # check output
 4875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4881     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4883     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4884     (check-next-stream-line-equal _test-output-stream "      b8/copy-to-eax 0/imm32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/9")
 4885     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4886     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4887     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4888     (check-next-stream-line-equal _test-output-stream "        03/add *(ebp+0xfffffff8) 0x00000000/r32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/13")
 4889     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/14")
 4890     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4891     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4892     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4893     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4895     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4897     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4898     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4899     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4900     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4901     # . epilogue
 4902     89/<- %esp 5/r32/ebp
 4903     5d/pop-to-ebp
 4904     c3/return
 4905 
 4906 test-convert-function-with-branches-and-local-vars:
 4907     # A conditional 'break' after a 'var' in a block is converted into a
 4908     # nested block that performs all necessary cleanup before jumping. This
 4909     # results in some ugly code duplication.
 4910     # . prologue
 4911     55/push-ebp
 4912     89/<- %ebp 4/r32/esp
 4913     # setup
 4914     (clear-stream _test-input-stream)
 4915     (clear-stream $_test-input-buffered-file->buffer)
 4916     (clear-stream _test-output-stream)
 4917     (clear-stream $_test-output-buffered-file->buffer)
 4918     #
 4919     (write _test-input-stream "fn foo {\n")
 4920     (write _test-input-stream "  {\n")
 4921     (write _test-input-stream "    var x: int\n")
 4922     (write _test-input-stream "    break-if->=\n")
 4923     (write _test-input-stream "    increment x\n")
 4924     (write _test-input-stream "  }\n")
 4925     (write _test-input-stream "}\n")
 4926     # convert
 4927     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4928     (flush _test-output-buffered-file)
 4929 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4935     # check output
 4936     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4937     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4938     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4939     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4940     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4942     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4943     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4944     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4945     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4946     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4947     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-local-vars/11")
 4948     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4949     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4950     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4951     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-local-vars/15")
 4952     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4954     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4955     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4956     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4957     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4958     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4959     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4960     # . epilogue
 4961     89/<- %esp 5/r32/ebp
 4962     5d/pop-to-ebp
 4963     c3/return
 4964 
 4965 test-convert-function-with-conditional-loops-and-local-vars:
 4966     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4967     # block that performs all necessary cleanup before jumping. This results
 4968     # in some ugly code duplication.
 4969     # . prologue
 4970     55/push-ebp
 4971     89/<- %ebp 4/r32/esp
 4972     # setup
 4973     (clear-stream _test-input-stream)
 4974     (clear-stream $_test-input-buffered-file->buffer)
 4975     (clear-stream _test-output-stream)
 4976     (clear-stream $_test-output-buffered-file->buffer)
 4977     #
 4978     (write _test-input-stream "fn foo {\n")
 4979     (write _test-input-stream "  {\n")
 4980     (write _test-input-stream "    var x: int\n")
 4981     (write _test-input-stream "    loop-if->=\n")
 4982     (write _test-input-stream "    increment x\n")
 4983     (write _test-input-stream "  }\n")
 4984     (write _test-input-stream "}\n")
 4985     # convert
 4986     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4987     (flush _test-output-buffered-file)
 4988 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4994     # check output
 4995     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4996     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4997     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4998     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4999     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 5000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 5001     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 5002     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 5003     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 5004     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 5005     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-conditional-loops-and-local-vars/10")
 5006     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-conditional-loops-and-local-vars/11")
 5007     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-conditional-loops-and-local-vars/12")
 5008     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 5009     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-conditional-loops-and-local-vars/14")
 5010     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-conditional-loops-and-local-vars/15")
 5011     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 5012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 5013     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 5014     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 5015     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 5016     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 5017     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 5018     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 5019     # . epilogue
 5020     89/<- %esp 5/r32/ebp
 5021     5d/pop-to-ebp
 5022     c3/return
 5023 
 5024 test-convert-function-with-unconditional-loops-and-local-vars:
 5025     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 5026     # regular block cleanup. Any instructions after 'loop' are dead and
 5027     # therefore skipped.
 5028     # . prologue
 5029     55/push-ebp
 5030     89/<- %ebp 4/r32/esp
 5031     # setup
 5032     (clear-stream _test-input-stream)
 5033     (clear-stream $_test-input-buffered-file->buffer)
 5034     (clear-stream _test-output-stream)
 5035     (clear-stream $_test-output-buffered-file->buffer)
 5036     #
 5037     (write _test-input-stream "fn foo {\n")
 5038     (write _test-input-stream "  {\n")
 5039     (write _test-input-stream "    var x: int\n")
 5040     (write _test-input-stream "    loop\n")
 5041     (write _test-input-stream "    increment x\n")
 5042     (write _test-input-stream "  }\n")
 5043     (write _test-input-stream "}\n")
 5044     # convert
 5045     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5046     (flush _test-output-buffered-file)
 5047 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5053     # check output
 5054     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 5055     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 5056     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 5057     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 5058     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 5059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 5060     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 5061     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 5062     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 5063     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/9")
 5064     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 5065     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 5066     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 5067     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 5068     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 5069     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 5070     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 5071     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 5072     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 5073     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 5074     # . epilogue
 5075     89/<- %esp 5/r32/ebp
 5076     5d/pop-to-ebp
 5077     c3/return
 5078 
 5079 test-convert-function-with-branches-and-loops-and-local-vars:
 5080     # . prologue
 5081     55/push-ebp
 5082     89/<- %ebp 4/r32/esp
 5083     # setup
 5084     (clear-stream _test-input-stream)
 5085     (clear-stream $_test-input-buffered-file->buffer)
 5086     (clear-stream _test-output-stream)
 5087     (clear-stream $_test-output-buffered-file->buffer)
 5088     #
 5089     (write _test-input-stream "fn foo {\n")
 5090     (write _test-input-stream "  {\n")
 5091     (write _test-input-stream "    var x: int\n")
 5092     (write _test-input-stream "    break-if->=\n")
 5093     (write _test-input-stream "    increment x\n")
 5094     (write _test-input-stream "    loop\n")
 5095     (write _test-input-stream "  }\n")
 5096     (write _test-input-stream "}\n")
 5097     # convert
 5098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5099     (flush _test-output-buffered-file)
 5100 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5106     # check output
 5107     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 5108     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 5109     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 5110     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-loops-and-local-vars/3")
 5111     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 5112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 5113     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 5114     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 5115     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 5116     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 5117     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/10")
 5118     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/11")
 5119     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/12")
 5120     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 5121     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-loops-and-local-vars/14")
 5122     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/15")
 5123     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 5124     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 5125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 5126     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 5127     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 5128     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 5129     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-loops-and-local-vars/22")
 5130     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 5131     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 5132     # . epilogue
 5133     89/<- %esp 5/r32/ebp
 5134     5d/pop-to-ebp
 5135     c3/return
 5136 
 5137 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 5138     # . prologue
 5139     55/push-ebp
 5140     89/<- %ebp 4/r32/esp
 5141     # setup
 5142     (clear-stream _test-input-stream)
 5143     (clear-stream $_test-input-buffered-file->buffer)
 5144     (clear-stream _test-output-stream)
 5145     (clear-stream $_test-output-buffered-file->buffer)
 5146     #
 5147     (write _test-input-stream "fn foo {\n")
 5148     (write _test-input-stream "  a: {\n")
 5149     (write _test-input-stream "    var x: int\n")
 5150     (write _test-input-stream "    {\n")
 5151     (write _test-input-stream "      var y: int\n")
 5152     (write _test-input-stream "      break-if->= a\n")
 5153     (write _test-input-stream "      increment x\n")
 5154     (write _test-input-stream "      loop\n")
 5155     (write _test-input-stream "    }\n")
 5156     (write _test-input-stream "  }\n")
 5157     (write _test-input-stream "}\n")
 5158     # convert
 5159     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5160     (flush _test-output-buffered-file)
 5161 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5167     # check output
 5168     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 5169     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 5170     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 5171     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3")
 5172     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 5173     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 5174     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 5175     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 5176     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8")
 5177     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 5178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 5179     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11")
 5180     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 5181     (check-next-stream-line-equal _test-output-stream "          0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13")
 5182     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14")
 5183     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15")
 5184     (check-next-stream-line-equal _test-output-stream "          e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16")
 5185     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 5186     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18")
 5187     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19")
 5188     (check-next-stream-line-equal _test-output-stream "        e9/jump loop/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20")
 5189     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 5190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 5191     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23")
 5192     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 5193     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 5194     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 5195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 5196     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 5197     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29")
 5198     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30")
 5199     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 5200     # . epilogue
 5201     89/<- %esp 5/r32/ebp
 5202     5d/pop-to-ebp
 5203     c3/return
 5204 
 5205 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 5206     # . prologue
 5207     55/push-ebp
 5208     89/<- %ebp 4/r32/esp
 5209     # setup
 5210     (clear-stream _test-input-stream)
 5211     (clear-stream $_test-input-buffered-file->buffer)
 5212     (clear-stream _test-output-stream)
 5213     (clear-stream $_test-output-buffered-file->buffer)
 5214     # non-local conditional branch from a block without a local variable,
 5215     # unwinding a local on the stack
 5216     (write _test-input-stream "fn foo {\n")
 5217     (write _test-input-stream "  a: {\n")
 5218     (write _test-input-stream "    var x: int\n")
 5219     (write _test-input-stream "    {\n")
 5220     (write _test-input-stream "      break-if->= a\n")
 5221     (write _test-input-stream "    }\n")
 5222     (write _test-input-stream "  }\n")
 5223     (write _test-input-stream "}\n")
 5224     # convert
 5225     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5226     (flush _test-output-buffered-file)
 5227 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5233     # check output
 5234     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 5235     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 5236     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/2")
 5237     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/3")
 5238     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 5239     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/5")
 5240     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 5241     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 5242     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/8")
 5243     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 5244     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/10")
 5245     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 5246     (check-next-stream-line-equal _test-output-stream "          0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/12")
 5247     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/13")
 5248     (check-next-stream-line-equal _test-output-stream "          e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/14")
 5249     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 5250     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 5251     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/17")
 5252     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/18")
 5253     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 5254     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 5255     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 5256     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/22")
 5257     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 5258     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/24")
 5259     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/25")
 5260     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 5261     # . epilogue
 5262     89/<- %esp 5/r32/ebp
 5263     5d/pop-to-ebp
 5264     c3/return
 5265 
 5266 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 5267     # . prologue
 5268     55/push-ebp
 5269     89/<- %ebp 4/r32/esp
 5270     # setup
 5271     (clear-stream _test-input-stream)
 5272     (clear-stream $_test-input-buffered-file->buffer)
 5273     (clear-stream _test-output-stream)
 5274     (clear-stream $_test-output-buffered-file->buffer)
 5275     # non-local unconditional branch from a block without a local variable,
 5276     # unwinding a local on the stack
 5277     (write _test-input-stream "fn foo {\n")
 5278     (write _test-input-stream "  a: {\n")
 5279     (write _test-input-stream "    var x: int\n")
 5280     (write _test-input-stream "    {\n")
 5281     (write _test-input-stream "      break a\n")
 5282     (write _test-input-stream "    }\n")
 5283     (write _test-input-stream "  }\n")
 5284     (write _test-input-stream "}\n")
 5285     # convert
 5286     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5287     (flush _test-output-buffered-file)
 5288 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5294     # check output
 5295     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5296     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5297     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/2")
 5298     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/3")
 5299     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5300     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/5")
 5301     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5302     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5303     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/8")
 5304     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5305     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/10")
 5306     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/11")
 5307     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/12")
 5308     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5309     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/15")
 5310     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/16")
 5311     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5312     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/20")
 5315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5316     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/22")
 5317     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/23")
 5318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5319     # . epilogue
 5320     89/<- %esp 5/r32/ebp
 5321     5d/pop-to-ebp
 5322     c3/return
 5323 
 5324 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5325     # . prologue
 5326     55/push-ebp
 5327     89/<- %ebp 4/r32/esp
 5328     # setup
 5329     (clear-stream _test-input-stream)
 5330     (clear-stream $_test-input-buffered-file->buffer)
 5331     (clear-stream _test-output-stream)
 5332     (clear-stream $_test-output-buffered-file->buffer)
 5333     #
 5334     (write _test-input-stream "fn foo {\n")
 5335     (write _test-input-stream "  a: {\n")
 5336     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5337     (write _test-input-stream "    {\n")
 5338     (write _test-input-stream "      break a\n")
 5339     (write _test-input-stream "    }\n")
 5340     (write _test-input-stream "  }\n")
 5341     (write _test-input-stream "}\n")
 5342     # convert
 5343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5344     (flush _test-output-buffered-file)
 5345 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5351     # check output
 5352     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/2")
 5355     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/3")
 5356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/5")
 5358     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5359     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5360     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/8")
 5361     (check-next-stream-line-equal _test-output-stream "      be/copy-to-esi 0/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/9")
 5362     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/11")
 5364     (check-next-stream-line-equal _test-output-stream "        8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/12")
 5365     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/13")
 5366     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5367     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/15")
 5368     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/16")
 5369     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5370     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5371     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5372     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/20")
 5373     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5374     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/22")
 5375     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/23")
 5376     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5377     # . epilogue
 5378     89/<- %esp 5/r32/ebp
 5379     5d/pop-to-ebp
 5380     c3/return
 5381 
 5382 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5383     # . prologue
 5384     55/push-ebp
 5385     89/<- %ebp 4/r32/esp
 5386     # setup
 5387     (clear-stream _test-input-stream)
 5388     (clear-stream $_test-input-buffered-file->buffer)
 5389     (clear-stream _test-output-stream)
 5390     (clear-stream $_test-output-buffered-file->buffer)
 5391     #
 5392     (write _test-input-stream "fn foo {\n")
 5393     (write _test-input-stream "  a: {\n")
 5394     (write _test-input-stream "    var x: int\n")
 5395     (write _test-input-stream "    {\n")
 5396     (write _test-input-stream "      var y: int\n")
 5397     (write _test-input-stream "      break a\n")
 5398     (write _test-input-stream "      increment x\n")
 5399     (write _test-input-stream "    }\n")
 5400     (write _test-input-stream "  }\n")
 5401     (write _test-input-stream "}\n")
 5402     # convert
 5403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5404     (flush _test-output-buffered-file)
 5405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5411     # check output
 5412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5415     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3")
 5416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5418     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5419     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5420     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5421     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5423     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5424     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12")
 5425     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13")
 5426     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14")
 5427     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5429     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17")
 5430     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5431     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5432     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5434     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5435     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23")
 5436     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5437     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5438     # . epilogue
 5439     89/<- %esp 5/r32/ebp
 5440     5d/pop-to-ebp
 5441     c3/return
 5442 
 5443 test-convert-function-with-unconditional-break-and-local-vars:
 5444     # . prologue
 5445     55/push-ebp
 5446     89/<- %ebp 4/r32/esp
 5447     # setup
 5448     (clear-stream _test-input-stream)
 5449     (clear-stream $_test-input-buffered-file->buffer)
 5450     (clear-stream _test-output-stream)
 5451     (clear-stream $_test-output-buffered-file->buffer)
 5452     #
 5453     (write _test-input-stream "fn foo {\n")
 5454     (write _test-input-stream "  {\n")
 5455     (write _test-input-stream "    var x: int\n")
 5456     (write _test-input-stream "    {\n")
 5457     (write _test-input-stream "      var y: int\n")
 5458     (write _test-input-stream "      break\n")
 5459     (write _test-input-stream "      increment x\n")
 5460     (write _test-input-stream "    }\n")
 5461     (write _test-input-stream "  }\n")
 5462     (write _test-input-stream "}\n")
 5463     # convert
 5464     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5465     (flush _test-output-buffered-file)
 5466 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5472     # check output
 5473     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5474     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5475     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5476     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5477     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5478     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5479     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5481     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5482     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5483     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5484     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5485     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-break-and-local-vars/12")
 5486     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5487     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5488     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-break-and-local-vars/15")
 5489     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5491     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5492     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5493     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5494     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5495     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5496     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5497     # . epilogue
 5498     89/<- %esp 5/r32/ebp
 5499     5d/pop-to-ebp
 5500     c3/return
 5501 
 5502 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5503     # . prologue
 5504     55/push-ebp
 5505     89/<- %ebp 4/r32/esp
 5506     # setup
 5507     (clear-stream _test-input-stream)
 5508     (clear-stream $_test-input-buffered-file->buffer)
 5509     (clear-stream _test-output-stream)
 5510     (clear-stream $_test-output-buffered-file->buffer)
 5511     #
 5512     (write _test-input-stream "fn foo {\n")
 5513     (write _test-input-stream "  a: {\n")
 5514     (write _test-input-stream "    var x: int\n")
 5515     (write _test-input-stream "    {\n")
 5516     (write _test-input-stream "      var y: int\n")
 5517     (write _test-input-stream "      loop a\n")
 5518     (write _test-input-stream "      increment x\n")
 5519     (write _test-input-stream "    }\n")
 5520     (write _test-input-stream "  }\n")
 5521     (write _test-input-stream "}\n")
 5522     # convert
 5523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5524     (flush _test-output-buffered-file)
 5525 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5531     # check output
 5532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5535     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3")
 5536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5538     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5539     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5540     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5541     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5543     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5544     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12")
 5545     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13")
 5546     (check-next-stream-line-equal _test-output-stream "        e9/jump a:loop/disp32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14")
 5547     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5548     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5549     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17")
 5550     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5551     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5552     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5555     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23")
 5556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5557     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5558     # . epilogue
 5559     89/<- %esp 5/r32/ebp
 5560     5d/pop-to-ebp
 5561     c3/return
 5562 
 5563 test-convert-function-with-local-array-var-in-mem:
 5564     # . prologue
 5565     55/push-ebp
 5566     89/<- %ebp 4/r32/esp
 5567     # setup
 5568     (clear-stream _test-input-stream)
 5569     (clear-stream $_test-input-buffered-file->buffer)
 5570     (clear-stream _test-output-stream)
 5571     (clear-stream $_test-output-buffered-file->buffer)
 5572     #
 5573     (write _test-input-stream "fn foo {\n")
 5574     (write _test-input-stream "  var x: (array int 3)\n")
 5575     (write _test-input-stream "}\n")
 5576     # convert
 5577     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5578     (flush _test-output-buffered-file)
 5579 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5585     # check output
 5586     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5587     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5588     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5589     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5590     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5591     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5592     # define x
 5593     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5594     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5595     # reclaim x
 5596     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-function-with-local-array-var-in-mem/9")
 5597     #
 5598     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5600     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5601     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5602     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5603     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5604     # . epilogue
 5605     89/<- %esp 5/r32/ebp
 5606     5d/pop-to-ebp
 5607     c3/return
 5608 
 5609 test-array-size-in-hex:
 5610     # . prologue
 5611     55/push-ebp
 5612     89/<- %ebp 4/r32/esp
 5613     # setup
 5614     (clear-stream _test-input-stream)
 5615     (clear-stream $_test-input-buffered-file->buffer)
 5616     (clear-stream _test-output-stream)
 5617     (clear-stream $_test-output-buffered-file->buffer)
 5618     (clear-stream _test-error-stream)
 5619     (clear-stream $_test-error-buffered-file->buffer)
 5620     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5621     68/push 0/imm32
 5622     68/push 0/imm32
 5623     89/<- %edx 4/r32/esp
 5624     (tailor-exit-descriptor %edx 0x10)
 5625     #
 5626     (write _test-input-stream "fn foo {\n")
 5627     (write _test-input-stream "  var x: (array int 10)\n")
 5628     (write _test-input-stream "}\n")
 5629     # convert
 5630     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5631     # registers except esp clobbered at this point
 5632     # restore ed
 5633     89/<- %edx 4/r32/esp
 5634     (flush _test-output-buffered-file)
 5635     (flush _test-error-buffered-file)
 5636 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5642     # check output
 5643     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5644     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-array-size-in-hex: error message")
 5645     # check that stop(1) was called
 5646     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5647     # don't restore from ebp
 5648     81 0/subop/add %esp 8/imm32
 5649     # . epilogue
 5650     5d/pop-to-ebp
 5651     c3/return
 5652 
 5653 test-array-size-with-metadata:
 5654     # . prologue
 5655     55/push-ebp
 5656     89/<- %ebp 4/r32/esp
 5657     # setup
 5658     (clear-stream _test-input-stream)
 5659     (clear-stream $_test-input-buffered-file->buffer)
 5660     (clear-stream _test-output-stream)
 5661     (clear-stream $_test-output-buffered-file->buffer)
 5662     #
 5663     (write _test-input-stream "fn foo {\n")
 5664     (write _test-input-stream "  var x: (array int 3/bar)\n")
 5665     (write _test-input-stream "}\n")
 5666     # convert
 5667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5668     (flush _test-output-buffered-file)
 5669 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5675     # no errors
 5676     # . epilogue
 5677     89/<- %esp 5/r32/ebp
 5678     5d/pop-to-ebp
 5679     c3/return
 5680 
 5681 test-convert-function-with-populate:
 5682     # . prologue
 5683     55/push-ebp
 5684     89/<- %ebp 4/r32/esp
 5685     # setup
 5686     (clear-stream _test-input-stream)
 5687     (clear-stream $_test-input-buffered-file->buffer)
 5688     (clear-stream _test-output-stream)
 5689     (clear-stream $_test-output-buffered-file->buffer)
 5690     #
 5691     (write _test-input-stream "fn foo {\n")
 5692     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5693     (write _test-input-stream "  populate x, 7\n")
 5694     (write _test-input-stream "}\n")
 5695     # convert
 5696     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5697     (flush _test-output-buffered-file)
 5698 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5704     # check output
 5705     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5706     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5707     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5708     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5709     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5710     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5711     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5712     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5713     (check-next-stream-line-equal _test-output-stream "    (allocate-array2 Heap 0x00000004 7 %ecx)"  "F - test-convert-function-with-populate/8")  # 4 = size-of(int)
 5714     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5715     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5720     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5721     # . epilogue
 5722     89/<- %esp 5/r32/ebp
 5723     5d/pop-to-ebp
 5724     c3/return
 5725 
 5726 # special-case for size(byte) when allocating array
 5727 test-convert-function-with-local-array-of-bytes-in-mem:
 5728     # . prologue
 5729     55/push-ebp
 5730     89/<- %ebp 4/r32/esp
 5731     # setup
 5732     (clear-stream _test-input-stream)
 5733     (clear-stream $_test-input-buffered-file->buffer)
 5734     (clear-stream _test-output-stream)
 5735     (clear-stream $_test-output-buffered-file->buffer)
 5736     #
 5737     (write _test-input-stream "fn foo {\n")
 5738     (write _test-input-stream "  var x: (array byte 3)\n")
 5739     (write _test-input-stream "}\n")
 5740     # convert
 5741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5742     (flush _test-output-buffered-file)
 5743 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5749     # check output
 5750     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5751     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5752     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5753     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/3")
 5754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5755     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5756     # define x
 5757     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"  "F - test-convert-function-with-local-array-of-bytes-in-mem/7")
 5758     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5759     # reclaim x
 5760     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/9")
 5761     #
 5762     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5764     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5765     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/13")
 5766     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5767     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5768     # . epilogue
 5769     89/<- %esp 5/r32/ebp
 5770     5d/pop-to-ebp
 5771     c3/return
 5772 
 5773 test-convert-address:
 5774     # . prologue
 5775     55/push-ebp
 5776     89/<- %ebp 4/r32/esp
 5777     # setup
 5778     (clear-stream _test-input-stream)
 5779     (clear-stream $_test-input-buffered-file->buffer)
 5780     (clear-stream _test-output-stream)
 5781     (clear-stream $_test-output-buffered-file->buffer)
 5782     #
 5783     (write _test-input-stream "fn foo {\n")
 5784     (write _test-input-stream "  var a: int\n")
 5785     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5786     (write _test-input-stream "}\n")
 5787     # convert
 5788     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5789     (flush _test-output-buffered-file)
 5790 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5796     # check output
 5797     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5798     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5799     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5800     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5801     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5802     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5803     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5804     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5805     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5806     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5807     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5808     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5809     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5810     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5811     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5812     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5813     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5814     # . epilogue
 5815     89/<- %esp 5/r32/ebp
 5816     5d/pop-to-ebp
 5817     c3/return
 5818 
 5819 test-convert-floating-point-convert:
 5820     # . prologue
 5821     55/push-ebp
 5822     89/<- %ebp 4/r32/esp
 5823     # setup
 5824     (clear-stream _test-input-stream)
 5825     (clear-stream $_test-input-buffered-file->buffer)
 5826     (clear-stream _test-output-stream)
 5827     (clear-stream $_test-output-buffered-file->buffer)
 5828     #
 5829     (write _test-input-stream "fn foo {\n")
 5830     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5831     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5832     (write _test-input-stream "}\n")
 5833     # convert
 5834     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5835     (flush _test-output-buffered-file)
 5836 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5842     # check output
 5843     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5844     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5845     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5846     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5847     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5848     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5849     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5850     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5851     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5852     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5853     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5854     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5855     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5856     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5857     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5858     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5859     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5860     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5861     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5862     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5863     # . epilogue
 5864     89/<- %esp 5/r32/ebp
 5865     5d/pop-to-ebp
 5866     c3/return
 5867 
 5868 test-convert-floating-point-convert-2:
 5869     # . prologue
 5870     55/push-ebp
 5871     89/<- %ebp 4/r32/esp
 5872     # setup
 5873     (clear-stream _test-input-stream)
 5874     (clear-stream $_test-input-buffered-file->buffer)
 5875     (clear-stream _test-output-stream)
 5876     (clear-stream $_test-output-buffered-file->buffer)
 5877     #
 5878     (write _test-input-stream "fn foo {\n")
 5879     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5880     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5881     (write _test-input-stream "  a <- convert b\n")
 5882     (write _test-input-stream "}\n")
 5883     # convert
 5884     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5885     (flush _test-output-buffered-file)
 5886 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5892     # check output
 5893     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5894     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5895     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5896     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5897     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5898     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5899     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5900     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5901     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5902     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5903     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert-2/10")
 5904     (check-next-stream-line-equal _test-output-stream "    f3 0f 2d/convert-to-int %xmm1 0x00000000/r32"  "F - test-convert-floating-point-convert-2/11")
 5905     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5906     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5907     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5908     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5910     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5911     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5912     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5913     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5914     # . epilogue
 5915     89/<- %esp 5/r32/ebp
 5916     5d/pop-to-ebp
 5917     c3/return
 5918 
 5919 test-convert-floating-point-operation:
 5920     # . prologue
 5921     55/push-ebp
 5922     89/<- %ebp 4/r32/esp
 5923     # setup
 5924     (clear-stream _test-input-stream)
 5925     (clear-stream $_test-input-buffered-file->buffer)
 5926     (clear-stream _test-output-stream)
 5927     (clear-stream $_test-output-buffered-file->buffer)
 5928     #
 5929     (write _test-input-stream "fn f {\n")
 5930     (write _test-input-stream "  var m: float\n")
 5931     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5932     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5933     (write _test-input-stream "  x <- copy y\n")
 5934     (write _test-input-stream "  copy-to m, y\n")
 5935     (write _test-input-stream "  x <- add y\n")
 5936     (write _test-input-stream "  x <- add m\n")
 5937     (write _test-input-stream "  x <- subtract y\n")
 5938     (write _test-input-stream "  x <- subtract m\n")
 5939     (write _test-input-stream "  x <- multiply y\n")
 5940     (write _test-input-stream "  x <- multiply m\n")
 5941     (write _test-input-stream "  x <- divide y\n")
 5942     (write _test-input-stream "  x <- divide m\n")
 5943     (write _test-input-stream "  x <- reciprocal y\n")
 5944     (write _test-input-stream "  x <- reciprocal m\n")
 5945     (write _test-input-stream "  x <- square-root y\n")
 5946     (write _test-input-stream "  x <- square-root m\n")
 5947     (write _test-input-stream "  x <- inverse-square-root y\n")
 5948     (write _test-input-stream "  x <- inverse-square-root m\n")
 5949     (write _test-input-stream "  x <- max y\n")
 5950     (write _test-input-stream "  x <- max m\n")
 5951     (write _test-input-stream "  x <- min y\n")
 5952     (write _test-input-stream "  x <- min m\n")
 5953     (write _test-input-stream "  compare x, y\n")
 5954     (write _test-input-stream "  compare x, m\n")
 5955     (write _test-input-stream "}\n")
 5956     # convert
 5957     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5958     (flush _test-output-buffered-file)
 5959 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5965     # check output
 5966     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5967     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5968     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5969     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5970     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5971     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5972     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5973     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5974     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5975     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5976     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5977     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5978     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5979     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5980     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5981     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5982     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5983     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5984     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5985     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5986     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5987     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5988     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5989     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5990     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5991     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5992     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5993     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5994     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root *(ebp+0xfffffffc) 0x00000001/x32"      "F - test-convert-floating-point-operation/28")
 5995     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5996     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5997     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5998     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5999     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
 6000     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 6002     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 6003     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 6004     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 6005     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 6006     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 6007     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 6008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 6009     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 6010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 6011     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 6012     # . epilogue
 6013     89/<- %esp 5/r32/ebp
 6014     5d/pop-to-ebp
 6015     c3/return
 6016 
 6017 test-convert-floating-point-dereferenced:
 6018     # . prologue
 6019     55/push-ebp
 6020     89/<- %ebp 4/r32/esp
 6021     # setup
 6022     (clear-stream _test-input-stream)
 6023     (clear-stream $_test-input-buffered-file->buffer)
 6024     (clear-stream _test-output-stream)
 6025     (clear-stream $_test-output-buffered-file->buffer)
 6026     #
 6027     (write _test-input-stream "fn f {\n")
 6028     (write _test-input-stream "  var m: float\n")
 6029     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 6030     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 6031     (write _test-input-stream "  x <- multiply *y\n")
 6032     (write _test-input-stream "}\n")
 6033     # convert
 6034     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6035     (flush _test-output-buffered-file)
 6036 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6042     # check output
 6043     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 6044     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 6045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 6046     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 6047     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 6048     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 6049     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 6050     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 6051     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 6052     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 6053     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 6054     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 6055     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 6056     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 6057     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 6058     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 6059     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 6060     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 6061     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 6062     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 6063     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 6064     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 6065     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 6066     # . epilogue
 6067     89/<- %esp 5/r32/ebp
 6068     5d/pop-to-ebp
 6069     c3/return
 6070 
 6071 test-convert-length-of-array:
 6072     # . prologue
 6073     55/push-ebp
 6074     89/<- %ebp 4/r32/esp
 6075     # setup
 6076     (clear-stream _test-input-stream)
 6077     (clear-stream $_test-input-buffered-file->buffer)
 6078     (clear-stream _test-output-stream)
 6079     (clear-stream $_test-output-buffered-file->buffer)
 6080     #
 6081     (write _test-input-stream "fn foo a: (addr array int) {\n")
 6082     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 6083     (write _test-input-stream "  var c/eax: int <- length b\n")
 6084     (write _test-input-stream "}\n")
 6085     # convert
 6086     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6087     (flush _test-output-buffered-file)
 6088 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6094     # check output
 6095     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 6096     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 6097     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 6098     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 6099     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 6100     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 6101     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 6102     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 6103     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 6104     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 6105     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 6106     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 6107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 6108     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 6109     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 6110     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 6111     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 6112     # . epilogue
 6113     89/<- %esp 5/r32/ebp
 6114     5d/pop-to-ebp
 6115     c3/return
 6116 
 6117 # special-case for size(byte) when computing array length
 6118 test-convert-length-of-array-of-bytes:
 6119     # . prologue
 6120     55/push-ebp
 6121     89/<- %ebp 4/r32/esp
 6122     # setup
 6123     (clear-stream _test-input-stream)
 6124     (clear-stream $_test-input-buffered-file->buffer)
 6125     (clear-stream _test-output-stream)
 6126     (clear-stream $_test-output-buffered-file->buffer)
 6127     #
 6128     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 6129     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 6130     (write _test-input-stream "  var c/eax: int <- length b\n")
 6131     (write _test-input-stream "}\n")
 6132     # convert
 6133     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6134     (flush _test-output-buffered-file)
 6135 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6141     # check output
 6142     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 6143     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 6144     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 6145     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 6146     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 6147     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 6148     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 6149     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 6150     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 6151     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 6152     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 6153     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 6154     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 6155     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 6156     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 6157     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 6158     # . epilogue
 6159     89/<- %esp 5/r32/ebp
 6160     5d/pop-to-ebp
 6161     c3/return
 6162 
 6163 test-convert-length-of-array-on-stack:
 6164     # . prologue
 6165     55/push-ebp
 6166     89/<- %ebp 4/r32/esp
 6167     # setup
 6168     (clear-stream _test-input-stream)
 6169     (clear-stream $_test-input-buffered-file->buffer)
 6170     (clear-stream _test-output-stream)
 6171     (clear-stream $_test-output-buffered-file->buffer)
 6172     #
 6173     (write _test-input-stream "fn foo {\n")
 6174     (write _test-input-stream "  var a: (array int 3)\n")
 6175     (write _test-input-stream "  var b/eax: int <- length a\n")
 6176     (write _test-input-stream "}\n")
 6177     # convert
 6178     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6179     (flush _test-output-buffered-file)
 6180 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6186     # check output
 6187     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 6188     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 6189     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 6190     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 6191     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 6192     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 6193     # define x
 6194     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 6195     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 6196     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 6197     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 6198     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 6199     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 6200     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 6201     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 6202     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 6203     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 6204     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 6205     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 6206     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 6207     # . epilogue
 6208     89/<- %esp 5/r32/ebp
 6209     5d/pop-to-ebp
 6210     c3/return
 6211 
 6212 test-reg-var-def-with-read-of-same-register:
 6213     # . prologue
 6214     55/push-ebp
 6215     89/<- %ebp 4/r32/esp
 6216     # setup
 6217     (clear-stream _test-input-stream)
 6218     (clear-stream $_test-input-buffered-file->buffer)
 6219     (clear-stream _test-output-stream)
 6220     (clear-stream $_test-output-buffered-file->buffer)
 6221     (clear-stream _test-error-stream)
 6222     (clear-stream $_test-error-buffered-file->buffer)
 6223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 6224     68/push 0/imm32
 6225     68/push 0/imm32
 6226     89/<- %edx 4/r32/esp
 6227     (tailor-exit-descriptor %edx 0x10)
 6228     #
 6229     (write _test-input-stream "fn foo {\n")
 6230     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 6231     (write _test-input-stream "  var y/eax: int <- add x\n")
 6232     (write _test-input-stream "}\n")
 6233     # convert
 6234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6235     # registers except esp could be clobbered at this point (though they shouldn't be)
 6236     # restore ed
 6237     89/<- %edx 4/r32/esp
 6238     (flush _test-output-buffered-file)
 6239     (flush _test-error-buffered-file)
 6240 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6246 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6252     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 6253     # check output
 6254     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 6255     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 6256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 6257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 6258     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 6259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 6260     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 6261     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 6262     (check-next-stream-line-equal _test-output-stream "    01/add-to %eax 0x00000000/r32"           "F - test-reg-var-def-with-read-of-same-register/8")
 6263     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 6264     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 6265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 6266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 6267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 6268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 6269     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 6270     # don't restore from ebp
 6271     81 0/subop/add %esp 8/imm32
 6272     # . epilogue
 6273     5d/pop-to-ebp
 6274     c3/return
 6275 
 6276 test-convert-index-into-array:
 6277     # . prologue
 6278     55/push-ebp
 6279     89/<- %ebp 4/r32/esp
 6280     # setup
 6281     (clear-stream _test-input-stream)
 6282     (clear-stream $_test-input-buffered-file->buffer)
 6283     (clear-stream _test-output-stream)
 6284     (clear-stream $_test-output-buffered-file->buffer)
 6285     #
 6286     (write _test-input-stream "fn foo {\n")
 6287     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6288     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6289     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6290     (write _test-input-stream "}\n")
 6291     # convert
 6292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6293     (flush _test-output-buffered-file)
 6294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6300     # check output
 6301     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 6302     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 6303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 6304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 6305     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 6306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 6307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 6308     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 6309     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 6310     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6311     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6312     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array/11")
 6313     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array/12")
 6314     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/13")
 6315     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/14")
 6316     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/15")
 6317     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/16")
 6318     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/17")
 6319     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/18")
 6320     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/19")
 6321     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/20")
 6322     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/21")
 6323     # . epilogue
 6324     89/<- %esp 5/r32/ebp
 6325     5d/pop-to-ebp
 6326     c3/return
 6327 
 6328 test-convert-index-into-array-of-bytes:
 6329     # . prologue
 6330     55/push-ebp
 6331     89/<- %ebp 4/r32/esp
 6332     # setup
 6333     (clear-stream _test-input-stream)
 6334     (clear-stream $_test-input-buffered-file->buffer)
 6335     (clear-stream _test-output-stream)
 6336     (clear-stream $_test-output-buffered-file->buffer)
 6337     #
 6338     (write _test-input-stream "fn foo {\n")
 6339     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6340     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6341     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6342     (write _test-input-stream "}\n")
 6343     # convert
 6344     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6345     (flush _test-output-buffered-file)
 6346 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6352     # check output
 6353     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6354     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6355     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6356     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6357     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6359     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6360     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6361     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6362     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6363     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes/10")
 6364     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes/11")
 6365     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes/12")
 6366     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/13")
 6367     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/14")
 6368     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/15")
 6369     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/16")
 6370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/17")
 6371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/18")
 6372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/19")
 6373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/20")
 6374     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/21")
 6375     # . epilogue
 6376     89/<- %esp 5/r32/ebp
 6377     5d/pop-to-ebp
 6378     c3/return
 6379 
 6380 test-convert-index-into-array-with-literal:
 6381     # . prologue
 6382     55/push-ebp
 6383     89/<- %ebp 4/r32/esp
 6384     # setup
 6385     (clear-stream _test-input-stream)
 6386     (clear-stream $_test-input-buffered-file->buffer)
 6387     (clear-stream _test-output-stream)
 6388     (clear-stream $_test-output-buffered-file->buffer)
 6389     #
 6390     (write _test-input-stream "fn foo {\n")
 6391     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6392     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6393     (write _test-input-stream "}\n")
 6394     # convert
 6395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6396     (flush _test-output-buffered-file)
 6397 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6403     # check output
 6404     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6405     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6406     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6407     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6408     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6410     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6411     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6412     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-with-literal/8")
 6413     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-with-literal/9")
 6414     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-with-literal/10")
 6415                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6416     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/11")
 6417     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/12")
 6418     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/13")
 6419     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/14")
 6420     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/15")
 6421     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/16")
 6422     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/17")
 6423     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/18")
 6424     # . epilogue
 6425     89/<- %esp 5/r32/ebp
 6426     5d/pop-to-ebp
 6427     c3/return
 6428 
 6429 test-convert-index-into-array-of-bytes-with-literal:
 6430     # . prologue
 6431     55/push-ebp
 6432     89/<- %ebp 4/r32/esp
 6433     # setup
 6434     (clear-stream _test-input-stream)
 6435     (clear-stream $_test-input-buffered-file->buffer)
 6436     (clear-stream _test-output-stream)
 6437     (clear-stream $_test-output-buffered-file->buffer)
 6438     #
 6439     (write _test-input-stream "fn foo {\n")
 6440     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6441     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6442     (write _test-input-stream "}\n")
 6443     # convert
 6444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6445     (flush _test-output-buffered-file)
 6446 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6452     # check output
 6453     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6454     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6457     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6460     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-with-literal/7")
 6461     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 6462     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6463     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6464                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6465     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6466     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6467     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6468     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6469     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6470     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/16")
 6471     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/17")
 6472     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/18")
 6473     # . epilogue
 6474     89/<- %esp 5/r32/ebp
 6475     5d/pop-to-ebp
 6476     c3/return
 6477 
 6478 test-convert-index-into-array-on-stack:
 6479     # . prologue
 6480     55/push-ebp
 6481     89/<- %ebp 4/r32/esp
 6482     # setup
 6483     (clear-stream _test-input-stream)
 6484     (clear-stream $_test-input-buffered-file->buffer)
 6485     (clear-stream _test-output-stream)
 6486     (clear-stream $_test-output-buffered-file->buffer)
 6487     #
 6488     (write _test-input-stream "fn foo {\n")
 6489     (write _test-input-stream "  var arr: (array int 3)\n")
 6490     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6491     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6492     (write _test-input-stream "}\n")
 6493     # convert
 6494     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6495     (flush _test-output-buffered-file)
 6496 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6502     # check output
 6503     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6504     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6505     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6506     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6507     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6508     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6509     # var arr
 6510     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6511     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6512     # var idx
 6513     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6514     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6515     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack/10")
 6516     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6517     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/11")
 6518     # reclaim idx
 6519     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6520     # reclaim arr
 6521     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6522     #
 6523     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6524     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6525     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6526     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6527     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6528     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6529     # . epilogue
 6530     89/<- %esp 5/r32/ebp
 6531     5d/pop-to-ebp
 6532     c3/return
 6533 
 6534 test-convert-index-into-array-on-stack-with-literal:
 6535     # . prologue
 6536     55/push-ebp
 6537     89/<- %ebp 4/r32/esp
 6538     # setup
 6539     (clear-stream _test-input-stream)
 6540     (clear-stream $_test-input-buffered-file->buffer)
 6541     (clear-stream _test-output-stream)
 6542     (clear-stream $_test-output-buffered-file->buffer)
 6543     #
 6544     (write _test-input-stream "fn foo {\n")
 6545     (write _test-input-stream "  var arr: (array int 3)\n")
 6546     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6547     (write _test-input-stream "}\n")
 6548     # convert
 6549     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6550     (flush _test-output-buffered-file)
 6551 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6557     # check output
 6558     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6559     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6560     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6561     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6562     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6563     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6564     # var arr
 6565     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6566     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6567     # var x
 6568     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6569     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack-with-literal/9")
 6570     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6571     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/10")
 6572     # reclaim x
 6573     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6574     # reclaim arr
 6575     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/12")
 6576     #
 6577     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6578     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6579     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6580     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6581     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6582     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6583     # . epilogue
 6584     89/<- %esp 5/r32/ebp
 6585     5d/pop-to-ebp
 6586     c3/return
 6587 
 6588 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6589     # . prologue
 6590     55/push-ebp
 6591     89/<- %ebp 4/r32/esp
 6592     # setup
 6593     (clear-stream _test-input-stream)
 6594     (clear-stream $_test-input-buffered-file->buffer)
 6595     (clear-stream _test-output-stream)
 6596     (clear-stream $_test-output-buffered-file->buffer)
 6597     #
 6598     (write _test-input-stream "fn foo {\n")
 6599     (write _test-input-stream "  var arr: (array byte 3)\n")
 6600     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6601     (write _test-input-stream "}\n")
 6602     # convert
 6603     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6604     (flush _test-output-buffered-file)
 6605 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6611     # check output
 6612     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6613     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6614     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6615     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/3")
 6616     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6617     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6618     # var arr
 6619     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"          "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/6")
 6620     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"                "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/7")
 6621     # var x
 6622     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/8")
 6623     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
 6624     # x is at (ebp-7) + 4 + 2 = ebp-1
 6625     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
 6626     # reclaim x
 6627     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
 6628     # reclaim arr
 6629     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 6630     #
 6631     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6632     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6633     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6634     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 6635     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 6636     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6637     # . epilogue
 6638     89/<- %esp 5/r32/ebp
 6639     5d/pop-to-ebp
 6640     c3/return
 6641 
 6642 test-convert-index-into-array-using-offset:
 6643     # . prologue
 6644     55/push-ebp
 6645     89/<- %ebp 4/r32/esp
 6646     # setup
 6647     (clear-stream _test-input-stream)
 6648     (clear-stream $_test-input-buffered-file->buffer)
 6649     (clear-stream _test-output-stream)
 6650     (clear-stream $_test-output-buffered-file->buffer)
 6651     #
 6652     (write _test-input-stream "fn foo {\n")
 6653     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6654     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6655     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6656     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6657     (write _test-input-stream "}\n")
 6658     # convert
 6659     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6660     (flush _test-output-buffered-file)
 6661 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6667     # check output
 6668     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6669     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6670     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6671     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6672     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6673     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6674     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6675     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6676     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6677     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6678     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6679     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset/11")
 6680     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset/12")
 6681     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset/13")
 6682     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/15")
 6683     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/16")
 6684     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/17")
 6685     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/18")
 6686     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/19")
 6687     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/20")
 6688     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/21")
 6689     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/22")
 6690     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/23")
 6691     # . epilogue
 6692     89/<- %esp 5/r32/ebp
 6693     5d/pop-to-ebp
 6694     c3/return
 6695 
 6696 test-convert-index-into-array-of-bytes-using-offset:
 6697     # . prologue
 6698     55/push-ebp
 6699     89/<- %ebp 4/r32/esp
 6700     # setup
 6701     (clear-stream _test-input-stream)
 6702     (clear-stream $_test-input-buffered-file->buffer)
 6703     (clear-stream _test-output-stream)
 6704     (clear-stream $_test-output-buffered-file->buffer)
 6705     #
 6706     (write _test-input-stream "fn foo {\n")
 6707     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6708     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6709     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6710     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6711     (write _test-input-stream "}\n")
 6712     # convert
 6713     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6714     (flush _test-output-buffered-file)
 6715 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6721     # check output
 6722     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6723     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6724     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6725     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6726     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6727     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6728     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6729     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/7")
 6730     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6731     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/9")
 6732     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/10")
 6733     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
 6734     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
 6735     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6736     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6737     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6738     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6739     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6740     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6741     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6742     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6743     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/21")
 6744     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/22")
 6745     # . epilogue
 6746     89/<- %esp 5/r32/ebp
 6747     5d/pop-to-ebp
 6748     c3/return
 6749 
 6750 test-convert-index-into-array-using-offset-on-stack:
 6751     # . prologue
 6752     55/push-ebp
 6753     89/<- %ebp 4/r32/esp
 6754     # setup
 6755     (clear-stream _test-input-stream)
 6756     (clear-stream $_test-input-buffered-file->buffer)
 6757     (clear-stream _test-output-stream)
 6758     (clear-stream $_test-output-buffered-file->buffer)
 6759     #
 6760     (write _test-input-stream "fn foo {\n")
 6761     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6762     (write _test-input-stream "  var idx: int\n")
 6763     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6764     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6765     (write _test-input-stream "}\n")
 6766     # convert
 6767     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6768     (flush _test-output-buffered-file)
 6769 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6775     # check output
 6776     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6777     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6778     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6779     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6780     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6781     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6782     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6783     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset-on-stack/7")
 6784     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6785     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6786     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset-on-stack/10")
 6787     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset-on-stack/11")
 6788     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
 6789     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset-on-stack/13")
 6790     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/14")
 6791     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6792     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/16")
 6793     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/17")
 6794     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/18")
 6795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6796     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/20")
 6797     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/21")
 6798     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/22")
 6799     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/23")
 6800     # . epilogue
 6801     89/<- %esp 5/r32/ebp
 6802     5d/pop-to-ebp
 6803     c3/return
 6804 
 6805 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6806     # . prologue
 6807     55/push-ebp
 6808     89/<- %ebp 4/r32/esp
 6809     # setup
 6810     (clear-stream _test-input-stream)
 6811     (clear-stream $_test-input-buffered-file->buffer)
 6812     (clear-stream _test-output-stream)
 6813     (clear-stream $_test-output-buffered-file->buffer)
 6814     #
 6815     (write _test-input-stream "fn foo {\n")
 6816     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6817     (write _test-input-stream "  var idx: int\n")
 6818     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6819     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6820     (write _test-input-stream "}\n")
 6821     # convert
 6822     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6823     (flush _test-output-buffered-file)
 6824 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6830     # check output
 6831     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6832     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6833     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6834     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/3")
 6835     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6837     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/6")
 6838     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/7")
 6839     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/8")
 6840     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9")
 6841     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10")
 6842     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
 6843     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
 6844     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
 6845     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
 6846     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 6847     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6848     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6849     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6850     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 6851     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 6852     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
 6853     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/22")
 6854     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/23")
 6855     # . epilogue
 6856     89/<- %esp 5/r32/ebp
 6857     5d/pop-to-ebp
 6858     c3/return
 6859 
 6860 test-convert-function-and-type-definition:
 6861     # . prologue
 6862     55/push-ebp
 6863     89/<- %ebp 4/r32/esp
 6864     # setup
 6865     (clear-stream _test-input-stream)
 6866     (clear-stream $_test-input-buffered-file->buffer)
 6867     (clear-stream _test-output-stream)
 6868     (clear-stream $_test-output-buffered-file->buffer)
 6869     #
 6870     (write _test-input-stream "fn foo a: (addr t) {\n")
 6871     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6872     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6873     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6874     (write _test-input-stream "}\n")
 6875     (write _test-input-stream "type t {\n")
 6876     (write _test-input-stream "  x: int\n")
 6877     (write _test-input-stream "  y: int\n")
 6878     (write _test-input-stream "}\n")
 6879     # convert
 6880     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6881     (flush _test-output-buffered-file)
 6882 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6888     # check output
 6889     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6890     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6891     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6892     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6893     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6895     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6896     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6897     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6898     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/9")
 6899     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"  "F - test-convert-function-and-type-definition/10")
 6900     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6901     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/12")
 6902     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"  "F - test-convert-function-and-type-definition/13")
 6903     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/14")
 6904     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/15")
 6905     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/16")
 6906     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/17")
 6907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/18")
 6908     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/19")
 6909     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/20")
 6910     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/21")
 6911     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/22")
 6912     # . epilogue
 6913     89/<- %esp 5/r32/ebp
 6914     5d/pop-to-ebp
 6915     c3/return
 6916 
 6917 test-type-definition-with-array:
 6918     # . prologue
 6919     55/push-ebp
 6920     89/<- %ebp 4/r32/esp
 6921     # setup
 6922     (clear-stream _test-input-stream)
 6923     (clear-stream $_test-input-buffered-file->buffer)
 6924     (clear-stream _test-output-stream)
 6925     (clear-stream $_test-output-buffered-file->buffer)
 6926     (clear-stream _test-error-stream)
 6927     (clear-stream $_test-error-buffered-file->buffer)
 6928     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6929     68/push 0/imm32
 6930     68/push 0/imm32
 6931     89/<- %edx 4/r32/esp
 6932     (tailor-exit-descriptor %edx 0x10)
 6933     #
 6934     (write _test-input-stream "type t {\n")
 6935     (write _test-input-stream "  a: (array int 3)\n")
 6936     (write _test-input-stream "}\n")
 6937     # convert
 6938     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6939     # registers except esp clobbered at this point
 6940     # restore ed
 6941     89/<- %edx 4/r32/esp
 6942     (flush _test-output-buffered-file)
 6943     (flush _test-error-buffered-file)
 6944 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6950     # check output
 6951     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6952     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6953     # check that stop(1) was called
 6954     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6955     # don't restore from ebp
 6956     81 0/subop/add %esp 8/imm32
 6957     # . epilogue
 6958     5d/pop-to-ebp
 6959     c3/return
 6960 
 6961 test-type-definition-with-addr:
 6962     # . prologue
 6963     55/push-ebp
 6964     89/<- %ebp 4/r32/esp
 6965     # setup
 6966     (clear-stream _test-input-stream)
 6967     (clear-stream $_test-input-buffered-file->buffer)
 6968     (clear-stream _test-output-stream)
 6969     (clear-stream $_test-output-buffered-file->buffer)
 6970     (clear-stream _test-error-stream)
 6971     (clear-stream $_test-error-buffered-file->buffer)
 6972     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6973     68/push 0/imm32
 6974     68/push 0/imm32
 6975     89/<- %edx 4/r32/esp
 6976     (tailor-exit-descriptor %edx 0x10)
 6977     #
 6978     (write _test-input-stream "type t {\n")
 6979     (write _test-input-stream "  a: (addr int)\n")
 6980     (write _test-input-stream "}\n")
 6981     # convert
 6982     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6983     # registers except esp clobbered at this point
 6984     # restore ed
 6985     89/<- %edx 4/r32/esp
 6986     (flush _test-output-buffered-file)
 6987     (flush _test-error-buffered-file)
 6988 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6994     # check output
 6995     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6996     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6997     # check that stop(1) was called
 6998     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6999     # don't restore from ebp
 7000     81 0/subop/add %esp 8/imm32
 7001     # . epilogue
 7002     5d/pop-to-ebp
 7003     c3/return
 7004 
 7005 test-convert-function-with-local-var-with-user-defined-type:
 7006     # . prologue
 7007     55/push-ebp
 7008     89/<- %ebp 4/r32/esp
 7009     # setup
 7010     (clear-stream _test-input-stream)
 7011     (clear-stream $_test-input-buffered-file->buffer)
 7012     (clear-stream _test-output-stream)
 7013     (clear-stream $_test-output-buffered-file->buffer)
 7014     #
 7015     (write _test-input-stream "fn foo {\n")
 7016     (write _test-input-stream "  var a: t\n")
 7017     (write _test-input-stream "}\n")
 7018     (write _test-input-stream "type t {\n")
 7019     (write _test-input-stream "  x: int\n")
 7020     (write _test-input-stream "  y: int\n")
 7021     (write _test-input-stream "}\n")
 7022     # convert
 7023     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7024     (flush _test-output-buffered-file)
 7025 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7031     # check output
 7032     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 7033     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 7034     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 7035     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type/3")
 7036     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 7037     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 7038     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 7039     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 7040     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type/8")
 7041     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 7042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 7043     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 7044     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type/12")
 7045     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 7046     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 7047     # . epilogue
 7048     89/<- %esp 5/r32/ebp
 7049     5d/pop-to-ebp
 7050     c3/return
 7051 
 7052 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 7053     # . prologue
 7054     55/push-ebp
 7055     89/<- %ebp 4/r32/esp
 7056     # setup
 7057     (clear-stream _test-input-stream)
 7058     (clear-stream $_test-input-buffered-file->buffer)
 7059     (clear-stream _test-output-stream)
 7060     (clear-stream $_test-output-buffered-file->buffer)
 7061     #
 7062     (write _test-input-stream "fn foo {\n")
 7063     (write _test-input-stream "  var a: t\n")
 7064     (write _test-input-stream "}\n")
 7065     (write _test-input-stream "type t {\n")
 7066     (write _test-input-stream "  x: s\n")
 7067     (write _test-input-stream "}\n")
 7068     (write _test-input-stream "type s {\n")
 7069     (write _test-input-stream "  z: int\n")
 7070     (write _test-input-stream "}\n")
 7071     # convert
 7072     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7073     (flush _test-output-buffered-file)
 7074 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7080     # check output
 7081     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/0")
 7082     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/1")
 7083     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/2")
 7084     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/3")
 7085     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 7086     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/5")
 7087     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/7")
 7088     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/8")
 7089     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 7090     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/10")
 7091     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/11")
 7092     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/12")
 7093     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/13")
 7094     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/14")
 7095     # . epilogue
 7096     89/<- %esp 5/r32/ebp
 7097     5d/pop-to-ebp
 7098     c3/return
 7099 
 7100 test-convert-function-call-with-arg-of-user-defined-type:
 7101     # . prologue
 7102     55/push-ebp
 7103     89/<- %ebp 4/r32/esp
 7104     # setup
 7105     (clear-stream _test-input-stream)
 7106     (clear-stream $_test-input-buffered-file->buffer)
 7107     (clear-stream _test-output-stream)
 7108     (clear-stream $_test-output-buffered-file->buffer)
 7109     #
 7110     (write _test-input-stream "fn f {\n")
 7111     (write _test-input-stream "  var a: t\n")
 7112     (write _test-input-stream "  foo a\n")
 7113     (write _test-input-stream "}\n")
 7114     (write _test-input-stream "fn foo x: t {\n")
 7115     (write _test-input-stream "}\n")
 7116     (write _test-input-stream "type t {\n")
 7117     (write _test-input-stream "  x: int\n")
 7118     (write _test-input-stream "  y: int\n")
 7119     (write _test-input-stream "}\n")
 7120     # convert
 7121     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7122     (flush _test-output-buffered-file)
 7123 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7129     # check output
 7130     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7131     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7132     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7133     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/3")
 7134     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7135     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7136     # var a: t
 7137     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 7138     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 7139     # foo a
 7140     (check-next-stream-line-equal _test-output-stream "    (foo *(ebp+0xfffffff8) *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-arg-of-user-defined-type/8")
 7141     #
 7142     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type/9")
 7143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7144     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7146     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/13")
 7147     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7149     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7150     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7151     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7152     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
 7153     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7154     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/21")
 7155     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7156     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7157     # . epilogue
 7158     89/<- %esp 5/r32/ebp
 7159     5d/pop-to-ebp
 7160     c3/return
 7161 
 7162 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 7163     # . prologue
 7164     55/push-ebp
 7165     89/<- %ebp 4/r32/esp
 7166     # setup
 7167     (clear-stream _test-input-stream)
 7168     (clear-stream $_test-input-buffered-file->buffer)
 7169     (clear-stream _test-output-stream)
 7170     (clear-stream $_test-output-buffered-file->buffer)
 7171     #
 7172     (write _test-input-stream "fn f {\n")
 7173     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 7174     (write _test-input-stream "  foo *a\n")
 7175     (write _test-input-stream "}\n")
 7176     (write _test-input-stream "fn foo x: t {\n")
 7177     (write _test-input-stream "}\n")
 7178     (write _test-input-stream "type t {\n")
 7179     (write _test-input-stream "  x: int\n")
 7180     (write _test-input-stream "  y: int\n")
 7181     (write _test-input-stream "}\n")
 7182     # convert
 7183     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7184     (flush _test-output-buffered-file)
 7185 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7191     # check output
 7192     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 7193     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 7194     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 7195     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/3")
 7196     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 7197     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 7198     # var a
 7199     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 7200     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 7201     # foo a
 7202     (check-next-stream-line-equal _test-output-stream "    (foo *(eax+0x00000000) *(eax+0x00000004))"  "F - test-convert-function-call-with-arg-of-user-defined-type/8")
 7203     #
 7204     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/9")
 7205     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 7206     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 7207     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 7208     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/13")
 7209     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 7210     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 7211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 7212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 7213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 7214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
 7215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 7216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/21")
 7217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 7218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 7219     # . epilogue
 7220     89/<- %esp 5/r32/ebp
 7221     5d/pop-to-ebp
 7222     c3/return
 7223 
 7224 # we don't have special support for call-by-reference; just explicitly create
 7225 # a new variable with the address of the arg
 7226 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 7227     # . prologue
 7228     55/push-ebp
 7229     89/<- %ebp 4/r32/esp
 7230     # setup
 7231     (clear-stream _test-input-stream)
 7232     (clear-stream $_test-input-buffered-file->buffer)
 7233     (clear-stream _test-output-stream)
 7234     (clear-stream $_test-output-buffered-file->buffer)
 7235     #
 7236     (write _test-input-stream "fn f {\n")
 7237     (write _test-input-stream "  var a: t\n")
 7238     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 7239     (write _test-input-stream "  foo b\n")
 7240     (write _test-input-stream "}\n")
 7241     (write _test-input-stream "fn foo x: (addr t) {\n")
 7242     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 7243     (write _test-input-stream "}\n")
 7244     (write _test-input-stream "type t {\n")
 7245     (write _test-input-stream "  x: int\n")
 7246     (write _test-input-stream "  y: int\n")
 7247     (write _test-input-stream "}\n")
 7248     # convert
 7249     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7250     (flush _test-output-buffered-file)
 7251 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7257     # check output
 7258     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 7259     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 7260     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/2")
 7261     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/3")
 7262     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 7263     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/5")
 7264     # var a: t
 7265     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/6")
 7266     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/7")
 7267     # var b/eax: (addr t)
 7268     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/8")
 7269     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffff8) 0x00000000/r32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/9")
 7270     # foo a
 7271     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 7272     #
 7273     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/11")
 7274     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/12")
 7275     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 7276     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/14")
 7277     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 7278     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/16")
 7279     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/17")
 7280     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 7281     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 7282     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 7283     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/21")
 7284     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/22")
 7285     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 7286     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/24")
 7287     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/25")
 7288     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000001/r32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/26")
 7289     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 7290     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 7291     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 7292     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 7293     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 7294     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32")
 7295     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 7296     # . epilogue
 7297     89/<- %esp 5/r32/ebp
 7298     5d/pop-to-ebp
 7299     c3/return
 7300 
 7301 test-convert-get-on-local-variable:
 7302     # . prologue
 7303     55/push-ebp
 7304     89/<- %ebp 4/r32/esp
 7305     # setup
 7306     (clear-stream _test-input-stream)
 7307     (clear-stream $_test-input-buffered-file->buffer)
 7308     (clear-stream _test-output-stream)
 7309     (clear-stream $_test-output-buffered-file->buffer)
 7310     #
 7311     (write _test-input-stream "fn foo {\n")
 7312     (write _test-input-stream "  var a: t\n")
 7313     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7314     (write _test-input-stream "}\n")
 7315     (write _test-input-stream "type t {\n")
 7316     (write _test-input-stream "  x: int\n")
 7317     (write _test-input-stream "  y: int\n")
 7318     (write _test-input-stream "}\n")
 7319     # convert
 7320     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7321     (flush _test-output-buffered-file)
 7322 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7328     # check output
 7329     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 7330     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7331     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7332     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7333     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7334     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7335     # var a
 7336     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7337     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7338     # var c
 7339     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7340     # get
 7341     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7342     # reclaim c
 7343     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7344     # reclaim a
 7345     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7346     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7347     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7348     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7349     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7350     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7351     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7352     # . epilogue
 7353     89/<- %esp 5/r32/ebp
 7354     5d/pop-to-ebp
 7355     c3/return
 7356 
 7357 test-convert-get-on-function-argument:
 7358     # . prologue
 7359     55/push-ebp
 7360     89/<- %ebp 4/r32/esp
 7361     # setup
 7362     (clear-stream _test-input-stream)
 7363     (clear-stream $_test-input-buffered-file->buffer)
 7364     (clear-stream _test-output-stream)
 7365     (clear-stream $_test-output-buffered-file->buffer)
 7366     #
 7367     (write _test-input-stream "fn foo a: t {\n")
 7368     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7369     (write _test-input-stream "}\n")
 7370     (write _test-input-stream "type t {\n")
 7371     (write _test-input-stream "  x: int\n")
 7372     (write _test-input-stream "  y: int\n")
 7373     (write _test-input-stream "}\n")
 7374     # convert
 7375     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7376     (flush _test-output-buffered-file)
 7377 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7383     # check output
 7384     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7385     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7386     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7387     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7388     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7390     # var c
 7391     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7392     # get
 7393     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7394     # reclaim c
 7395     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7396     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7397     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7398     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7399     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7400     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7401     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7402     # . epilogue
 7403     89/<- %esp 5/r32/ebp
 7404     5d/pop-to-ebp
 7405     c3/return
 7406 
 7407 test-convert-get-on-function-argument-with-known-type:
 7408     # . prologue
 7409     55/push-ebp
 7410     89/<- %ebp 4/r32/esp
 7411     # setup
 7412     (clear-stream _test-input-stream)
 7413     (clear-stream $_test-input-buffered-file->buffer)
 7414     (clear-stream _test-output-stream)
 7415     (clear-stream $_test-output-buffered-file->buffer)
 7416     #
 7417     (write _test-input-stream "type t {\n")
 7418     (write _test-input-stream "  x: int\n")
 7419     (write _test-input-stream "  y: int\n")
 7420     (write _test-input-stream "}\n")
 7421     (write _test-input-stream "fn foo a: t {\n")
 7422     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7423     (write _test-input-stream "}\n")
 7424     # convert
 7425     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7426     (flush _test-output-buffered-file)
 7427 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7433     # check output
 7434     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7435     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7436     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7437     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7438     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7439     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7440     # var c
 7441     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7442     # get
 7443     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument-with-known-type/7")
 7444     # reclaim c
 7445     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7446     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7447     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7448     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7449     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7450     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7451     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7452     # . epilogue
 7453     89/<- %esp 5/r32/ebp
 7454     5d/pop-to-ebp
 7455     c3/return
 7456 
 7457 test-add-with-too-many-inouts:
 7458     # . prologue
 7459     55/push-ebp
 7460     89/<- %ebp 4/r32/esp
 7461     # setup
 7462     (clear-stream _test-input-stream)
 7463     (clear-stream $_test-input-buffered-file->buffer)
 7464     (clear-stream _test-output-stream)
 7465     (clear-stream $_test-output-buffered-file->buffer)
 7466     (clear-stream _test-error-stream)
 7467     (clear-stream $_test-error-buffered-file->buffer)
 7468     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7469     68/push 0/imm32
 7470     68/push 0/imm32
 7471     89/<- %edx 4/r32/esp
 7472     (tailor-exit-descriptor %edx 0x10)
 7473     #
 7474     (write _test-input-stream "fn foo {\n")
 7475     (write _test-input-stream "  var a: int\n")
 7476     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7477     (write _test-input-stream "}\n")
 7478     # convert
 7479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7480     # registers except esp clobbered at this point
 7481     # restore ed
 7482     89/<- %edx 4/r32/esp
 7483     (flush _test-output-buffered-file)
 7484     (flush _test-error-buffered-file)
 7485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7491     # check output
 7492     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7493     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: too many inouts; most primitives support at most two arguments, across inouts and outputs"  "F - test-add-with-too-many-inouts: error message")
 7494     # check that stop(1) was called
 7495     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7496     # don't restore from ebp
 7497     81 0/subop/add %esp 8/imm32
 7498     # . epilogue
 7499     5d/pop-to-ebp
 7500     c3/return
 7501 
 7502 test-add-with-too-many-inouts-2:
 7503     # . prologue
 7504     55/push-ebp
 7505     89/<- %ebp 4/r32/esp
 7506     # setup
 7507     (clear-stream _test-input-stream)
 7508     (clear-stream $_test-input-buffered-file->buffer)
 7509     (clear-stream _test-output-stream)
 7510     (clear-stream $_test-output-buffered-file->buffer)
 7511     (clear-stream _test-error-stream)
 7512     (clear-stream $_test-error-buffered-file->buffer)
 7513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7514     68/push 0/imm32
 7515     68/push 0/imm32
 7516     89/<- %edx 4/r32/esp
 7517     (tailor-exit-descriptor %edx 0x10)
 7518     #
 7519     (write _test-input-stream "fn foo {\n")
 7520     (write _test-input-stream "  var a: int\n")
 7521     (write _test-input-stream "  add-to a, 0, 1\n")
 7522     (write _test-input-stream "}\n")
 7523     # convert
 7524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7525     # registers except esp clobbered at this point
 7526     # restore ed
 7527     89/<- %edx 4/r32/esp
 7528     (flush _test-output-buffered-file)
 7529     (flush _test-error-buffered-file)
 7530 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7536     # check output
 7537     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7538     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add-to: too many inouts; most primitives support at most two arguments, across inouts and outputs"  "F - test-add-with-too-many-inouts-2: error message")
 7539     # check that stop(1) was called
 7540     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7541     # don't restore from ebp
 7542     81 0/subop/add %esp 8/imm32
 7543     # . epilogue
 7544     5d/pop-to-ebp
 7545     c3/return
 7546 
 7547 test-add-with-too-many-outputs:
 7548     # . prologue
 7549     55/push-ebp
 7550     89/<- %ebp 4/r32/esp
 7551     # setup
 7552     (clear-stream _test-input-stream)
 7553     (clear-stream $_test-input-buffered-file->buffer)
 7554     (clear-stream _test-output-stream)
 7555     (clear-stream $_test-output-buffered-file->buffer)
 7556     (clear-stream _test-error-stream)
 7557     (clear-stream $_test-error-buffered-file->buffer)
 7558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7559     68/push 0/imm32
 7560     68/push 0/imm32
 7561     89/<- %edx 4/r32/esp
 7562     (tailor-exit-descriptor %edx 0x10)
 7563     #
 7564     (write _test-input-stream "fn foo {\n")
 7565     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7566     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7567     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7568     (write _test-input-stream "  c, b <- add a\n")
 7569     (write _test-input-stream "}\n")
 7570     # convert
 7571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7572     # registers except esp clobbered at this point
 7573     # restore ed
 7574     89/<- %edx 4/r32/esp
 7575     (flush _test-output-buffered-file)
 7576     (flush _test-error-buffered-file)
 7577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7583     # check output
 7584     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7585     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: too many outputs; most primitives support at most one output"  "F - test-add-with-too-many-outputs: error message")
 7586     # check that stop(1) was called
 7587     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7588     # don't restore from ebp
 7589     81 0/subop/add %esp 8/imm32
 7590     # . epilogue
 7591     5d/pop-to-ebp
 7592     c3/return
 7593 
 7594 test-add-with-non-number:
 7595     # . prologue
 7596     55/push-ebp
 7597     89/<- %ebp 4/r32/esp
 7598     # setup
 7599     (clear-stream _test-input-stream)
 7600     (clear-stream $_test-input-buffered-file->buffer)
 7601     (clear-stream _test-output-stream)
 7602     (clear-stream $_test-output-buffered-file->buffer)
 7603     (clear-stream _test-error-stream)
 7604     (clear-stream $_test-error-buffered-file->buffer)
 7605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7606     68/push 0/imm32
 7607     68/push 0/imm32
 7608     89/<- %edx 4/r32/esp
 7609     (tailor-exit-descriptor %edx 0x10)
 7610     #
 7611     (write _test-input-stream "fn foo {\n")
 7612     (write _test-input-stream "  var a: int\n")
 7613     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7614     (write _test-input-stream "}\n")
 7615     # convert
 7616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7617     # registers except esp clobbered at this point
 7618     # restore ed
 7619     89/<- %edx 4/r32/esp
 7620     (flush _test-output-buffered-file)
 7621     (flush _test-error-buffered-file)
 7622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7628     # check output
 7629     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7630     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: 'b' must be a non-addr non-offset scalar"  "F - test-add-with-non-number: error message")
 7631     # check that stop(1) was called
 7632     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7633     # don't restore from ebp
 7634     81 0/subop/add %esp 8/imm32
 7635     # . epilogue
 7636     5d/pop-to-ebp
 7637     c3/return
 7638 
 7639 test-add-with-addr-dereferenced:
 7640     # . prologue
 7641     55/push-ebp
 7642     89/<- %ebp 4/r32/esp
 7643     # setup
 7644     (clear-stream _test-input-stream)
 7645     (clear-stream $_test-input-buffered-file->buffer)
 7646     (clear-stream _test-output-stream)
 7647     (clear-stream $_test-output-buffered-file->buffer)
 7648     #
 7649     (write _test-input-stream "fn foo {\n")
 7650     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7651     (write _test-input-stream "  add-to *a, 1\n")
 7652     (write _test-input-stream "}\n")
 7653     # convert
 7654     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7655     (flush _test-output-buffered-file)
 7656     # no error
 7657     # . epilogue
 7658     89/<- %esp 5/r32/ebp
 7659     5d/pop-to-ebp
 7660     c3/return
 7661 
 7662 test-copy-with-no-inout:
 7663     # . prologue
 7664     55/push-ebp
 7665     89/<- %ebp 4/r32/esp
 7666     # setup
 7667     (clear-stream _test-input-stream)
 7668     (clear-stream $_test-input-buffered-file->buffer)
 7669     (clear-stream _test-output-stream)
 7670     (clear-stream $_test-output-buffered-file->buffer)
 7671     (clear-stream _test-error-stream)
 7672     (clear-stream $_test-error-buffered-file->buffer)
 7673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7674     68/push 0/imm32
 7675     68/push 0/imm32
 7676     89/<- %edx 4/r32/esp
 7677     (tailor-exit-descriptor %edx 0x10)
 7678     #
 7679     (write _test-input-stream "fn foo {\n")
 7680     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7681     (write _test-input-stream "}\n")
 7682     # convert
 7683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7684     # registers except esp clobbered at this point
 7685     # restore ed
 7686     89/<- %edx 4/r32/esp
 7687     (flush _test-output-buffered-file)
 7688     (flush _test-error-buffered-file)
 7689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7695     # check output
 7696     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7697     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7698     # check that stop(1) was called
 7699     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7700     # don't restore from ebp
 7701     81 0/subop/add %esp 8/imm32
 7702     # . epilogue
 7703     5d/pop-to-ebp
 7704     c3/return
 7705 
 7706 test-copy-with-multiple-inouts:
 7707     # . prologue
 7708     55/push-ebp
 7709     89/<- %ebp 4/r32/esp
 7710     # setup
 7711     (clear-stream _test-input-stream)
 7712     (clear-stream $_test-input-buffered-file->buffer)
 7713     (clear-stream _test-output-stream)
 7714     (clear-stream $_test-output-buffered-file->buffer)
 7715     (clear-stream _test-error-stream)
 7716     (clear-stream $_test-error-buffered-file->buffer)
 7717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7718     68/push 0/imm32
 7719     68/push 0/imm32
 7720     89/<- %edx 4/r32/esp
 7721     (tailor-exit-descriptor %edx 0x10)
 7722     #
 7723     (write _test-input-stream "fn foo {\n")
 7724     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7725     (write _test-input-stream "}\n")
 7726     # convert
 7727     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7728     # registers except esp clobbered at this point
 7729     # restore ed
 7730     89/<- %edx 4/r32/esp
 7731     (flush _test-output-buffered-file)
 7732     (flush _test-error-buffered-file)
 7733 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7739     # check output
 7740     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7741     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one inout"  "F - test-copy-with-multiple-inouts: error message")
 7742     # check that stop(1) was called
 7743     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7744     # don't restore from ebp
 7745     81 0/subop/add %esp 8/imm32
 7746     # . epilogue
 7747     5d/pop-to-ebp
 7748     c3/return
 7749 
 7750 test-copy-with-no-output:
 7751     # . prologue
 7752     55/push-ebp
 7753     89/<- %ebp 4/r32/esp
 7754     # setup
 7755     (clear-stream _test-input-stream)
 7756     (clear-stream $_test-input-buffered-file->buffer)
 7757     (clear-stream _test-output-stream)
 7758     (clear-stream $_test-output-buffered-file->buffer)
 7759     (clear-stream _test-error-stream)
 7760     (clear-stream $_test-error-buffered-file->buffer)
 7761     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7762     68/push 0/imm32
 7763     68/push 0/imm32
 7764     89/<- %edx 4/r32/esp
 7765     (tailor-exit-descriptor %edx 0x10)
 7766     #
 7767     (write _test-input-stream "fn foo {\n")
 7768     (write _test-input-stream "  copy 0\n")
 7769     (write _test-input-stream "}\n")
 7770     # convert
 7771     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7772     # registers except esp clobbered at this point
 7773     # restore ed
 7774     89/<- %edx 4/r32/esp
 7775     (flush _test-output-buffered-file)
 7776     (flush _test-error-buffered-file)
 7777 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7783     # check output
 7784     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7785     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7786     # check that stop(1) was called
 7787     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7788     # don't restore from ebp
 7789     81 0/subop/add %esp 8/imm32
 7790     # . epilogue
 7791     5d/pop-to-ebp
 7792     c3/return
 7793 
 7794 test-copy-with-multiple-outputs:
 7795     # . prologue
 7796     55/push-ebp
 7797     89/<- %ebp 4/r32/esp
 7798     # setup
 7799     (clear-stream _test-input-stream)
 7800     (clear-stream $_test-input-buffered-file->buffer)
 7801     (clear-stream _test-output-stream)
 7802     (clear-stream $_test-output-buffered-file->buffer)
 7803     (clear-stream _test-error-stream)
 7804     (clear-stream $_test-error-buffered-file->buffer)
 7805     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7806     68/push 0/imm32
 7807     68/push 0/imm32
 7808     89/<- %edx 4/r32/esp
 7809     (tailor-exit-descriptor %edx 0x10)
 7810     #
 7811     (write _test-input-stream "fn foo {\n")
 7812     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7813     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7814     (write _test-input-stream "  x, y <- copy 0\n")
 7815     (write _test-input-stream "}\n")
 7816     # convert
 7817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7818     # registers except esp clobbered at this point
 7819     # restore ed
 7820     89/<- %edx 4/r32/esp
 7821     (flush _test-output-buffered-file)
 7822     (flush _test-error-buffered-file)
 7823 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7829     # check output
 7830     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7831     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one output"  "F - test-copy-with-multiple-outputs: error message")
 7832     # check that stop(1) was called
 7833     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7834     # don't restore from ebp
 7835     81 0/subop/add %esp 8/imm32
 7836     # . epilogue
 7837     5d/pop-to-ebp
 7838     c3/return
 7839 
 7840 test-copy-invalid-value-to-address:
 7841     # . prologue
 7842     55/push-ebp
 7843     89/<- %ebp 4/r32/esp
 7844     # setup
 7845     (clear-stream _test-input-stream)
 7846     (clear-stream $_test-input-buffered-file->buffer)
 7847     (clear-stream _test-output-stream)
 7848     (clear-stream $_test-output-buffered-file->buffer)
 7849     (clear-stream _test-error-stream)
 7850     (clear-stream $_test-error-buffered-file->buffer)
 7851     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7852     68/push 0/imm32
 7853     68/push 0/imm32
 7854     89/<- %edx 4/r32/esp
 7855     (tailor-exit-descriptor %edx 0x10)
 7856     #
 7857     (write _test-input-stream "fn foo {\n")
 7858     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7859     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7860     (write _test-input-stream "}\n")
 7861     # convert
 7862     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7863     # registers except esp clobbered at this point
 7864     # restore ed
 7865     89/<- %edx 4/r32/esp
 7866     (flush _test-output-buffered-file)
 7867     (flush _test-error-buffered-file)
 7868 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7874     # check output
 7875     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7876     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7877     # check that stop(1) was called
 7878     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7879     # don't restore from ebp
 7880     81 0/subop/add %esp 8/imm32
 7881     # . epilogue
 7882     5d/pop-to-ebp
 7883     c3/return
 7884 
 7885 test-copy-null-value-to-address:
 7886     # . prologue
 7887     55/push-ebp
 7888     89/<- %ebp 4/r32/esp
 7889     # setup
 7890     (clear-stream _test-input-stream)
 7891     (clear-stream $_test-input-buffered-file->buffer)
 7892     (clear-stream _test-output-stream)
 7893     (clear-stream $_test-output-buffered-file->buffer)
 7894     #
 7895     (write _test-input-stream "fn foo {\n")
 7896     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7897     (write _test-input-stream "}\n")
 7898     # convert
 7899     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7900     (flush _test-output-buffered-file)
 7901     # no errors
 7902     # . epilogue
 7903     89/<- %esp 5/r32/ebp
 7904     5d/pop-to-ebp
 7905     c3/return
 7906 
 7907 test-copy-invalid-value-to-offset:
 7908     # . prologue
 7909     55/push-ebp
 7910     89/<- %ebp 4/r32/esp
 7911     # setup
 7912     (clear-stream _test-input-stream)
 7913     (clear-stream $_test-input-buffered-file->buffer)
 7914     (clear-stream _test-output-stream)
 7915     (clear-stream $_test-output-buffered-file->buffer)
 7916     (clear-stream _test-error-stream)
 7917     (clear-stream $_test-error-buffered-file->buffer)
 7918     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7919     68/push 0/imm32
 7920     68/push 0/imm32
 7921     89/<- %edx 4/r32/esp
 7922     (tailor-exit-descriptor %edx 0x10)
 7923     #
 7924     (write _test-input-stream "fn foo {\n")
 7925     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7926     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7927     (write _test-input-stream "}\n")
 7928     # convert
 7929     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7930     # registers except esp clobbered at this point
 7931     # restore ed
 7932     89/<- %edx 4/r32/esp
 7933     (flush _test-output-buffered-file)
 7934     (flush _test-error-buffered-file)
 7935 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7941     # check output
 7942     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7943     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7944     # check that stop(1) was called
 7945     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7946     # don't restore from ebp
 7947     81 0/subop/add %esp 8/imm32
 7948     # . epilogue
 7949     5d/pop-to-ebp
 7950     c3/return
 7951 
 7952 test-copy-null-value-to-offset:
 7953     # . prologue
 7954     55/push-ebp
 7955     89/<- %ebp 4/r32/esp
 7956     # setup
 7957     (clear-stream _test-input-stream)
 7958     (clear-stream $_test-input-buffered-file->buffer)
 7959     (clear-stream _test-output-stream)
 7960     (clear-stream $_test-output-buffered-file->buffer)
 7961     #
 7962     (write _test-input-stream "fn foo {\n")
 7963     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7964     (write _test-input-stream "}\n")
 7965     # convert
 7966     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7967     (flush _test-output-buffered-file)
 7968 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7974     # no errors
 7975     # . epilogue
 7976     89/<- %esp 5/r32/ebp
 7977     5d/pop-to-ebp
 7978     c3/return
 7979 
 7980 test-copy-non-literal-to-byte:
 7981     # . prologue
 7982     55/push-ebp
 7983     89/<- %ebp 4/r32/esp
 7984     # setup
 7985     (clear-stream _test-input-stream)
 7986     (clear-stream $_test-input-buffered-file->buffer)
 7987     (clear-stream _test-output-stream)
 7988     (clear-stream $_test-output-buffered-file->buffer)
 7989     (clear-stream _test-error-stream)
 7990     (clear-stream $_test-error-buffered-file->buffer)
 7991     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7992     68/push 0/imm32
 7993     68/push 0/imm32
 7994     89/<- %edx 4/r32/esp
 7995     (tailor-exit-descriptor %edx 0x10)
 7996     #
 7997     (write _test-input-stream "fn foo {\n")
 7998     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 7999     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
 8000     (write _test-input-stream "}\n")
 8001     # convert
 8002     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8003     # registers except esp clobbered at this point
 8004     # restore ed
 8005     89/<- %edx 4/r32/esp
 8006     (flush _test-output-buffered-file)
 8007     (flush _test-error-buffered-file)
 8008 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8014     # check output
 8015     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
 8016     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte"  "F - test-copy-non-literal-to-byte: error message")
 8017     # check that stop(1) was called
 8018     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
 8019     # don't restore from ebp
 8020     81 0/subop/add %esp 8/imm32
 8021     # . epilogue
 8022     5d/pop-to-ebp
 8023     c3/return
 8024 
 8025 test-copy-deref-address:
 8026     # . prologue
 8027     55/push-ebp
 8028     89/<- %ebp 4/r32/esp
 8029     # setup
 8030     (clear-stream _test-input-stream)
 8031     (clear-stream $_test-input-buffered-file->buffer)
 8032     (clear-stream _test-output-stream)
 8033     (clear-stream $_test-output-buffered-file->buffer)
 8034     #
 8035     (write _test-input-stream "fn foo {\n")
 8036     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 8037     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 8038     (write _test-input-stream "}\n")
 8039     # convert
 8040     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8041     (flush _test-output-buffered-file)
 8042     # no errors
 8043     # . epilogue
 8044     5d/pop-to-ebp
 8045     c3/return
 8046 
 8047 test-copy-to-non-register:
 8048     # . prologue
 8049     55/push-ebp
 8050     89/<- %ebp 4/r32/esp
 8051     # setup
 8052     (clear-stream _test-input-stream)
 8053     (clear-stream $_test-input-buffered-file->buffer)
 8054     (clear-stream _test-output-stream)
 8055     (clear-stream $_test-output-buffered-file->buffer)
 8056     (clear-stream _test-error-stream)
 8057     (clear-stream $_test-error-buffered-file->buffer)
 8058     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8059     68/push 0/imm32
 8060     68/push 0/imm32
 8061     89/<- %edx 4/r32/esp
 8062     (tailor-exit-descriptor %edx 0x10)
 8063     #
 8064     (write _test-input-stream "fn foo {\n")
 8065     (write _test-input-stream "  var x: int\n")
 8066     (write _test-input-stream "  x <- copy 0\n")
 8067     (write _test-input-stream "}\n")
 8068     # convert
 8069     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8070     # registers except esp clobbered at this point
 8071     # restore ed
 8072     89/<- %edx 4/r32/esp
 8073     (flush _test-output-buffered-file)
 8074     (flush _test-error-buffered-file)
 8075 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8081     # check output
 8082     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 8083     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: output 'x' not in a register"  "F - test-copy-to-non-register: error message")
 8084     # check that stop(1) was called
 8085     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 8086     # don't restore from ebp
 8087     81 0/subop/add %esp 8/imm32
 8088     # . epilogue
 8089     5d/pop-to-ebp
 8090     c3/return
 8091 
 8092 test-copy-from-non-scalar-inout:
 8093     # . prologue
 8094     55/push-ebp
 8095     89/<- %ebp 4/r32/esp
 8096     # setup
 8097     (clear-stream _test-input-stream)
 8098     (clear-stream $_test-input-buffered-file->buffer)
 8099     (clear-stream _test-output-stream)
 8100     (clear-stream $_test-output-buffered-file->buffer)
 8101     (clear-stream _test-error-stream)
 8102     (clear-stream $_test-error-buffered-file->buffer)
 8103     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8104     68/push 0/imm32
 8105     68/push 0/imm32
 8106     89/<- %edx 4/r32/esp
 8107     (tailor-exit-descriptor %edx 0x10)
 8108     #
 8109     (write _test-input-stream "fn foo {\n")
 8110     (write _test-input-stream "  var x: (handle int)\n")
 8111     (write _test-input-stream "  var y/eax: int <- copy x\n")
 8112     (write _test-input-stream "}\n")
 8113     # convert
 8114     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8115     # registers except esp clobbered at this point
 8116     # restore ed
 8117     89/<- %edx 4/r32/esp
 8118     (flush _test-output-buffered-file)
 8119     (flush _test-error-buffered-file)
 8120 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8126     # check output
 8127     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
 8128     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-from-non-scalar-inout: error message")
 8129     # check that stop(1) was called
 8130     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
 8131     # don't restore from ebp
 8132     81 0/subop/add %esp 8/imm32
 8133     # . epilogue
 8134     5d/pop-to-ebp
 8135     c3/return
 8136 
 8137 test-copy-to-with-no-inout:
 8138     # . prologue
 8139     55/push-ebp
 8140     89/<- %ebp 4/r32/esp
 8141     # setup
 8142     (clear-stream _test-input-stream)
 8143     (clear-stream $_test-input-buffered-file->buffer)
 8144     (clear-stream _test-output-stream)
 8145     (clear-stream $_test-output-buffered-file->buffer)
 8146     (clear-stream _test-error-stream)
 8147     (clear-stream $_test-error-buffered-file->buffer)
 8148     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8149     68/push 0/imm32
 8150     68/push 0/imm32
 8151     89/<- %edx 4/r32/esp
 8152     (tailor-exit-descriptor %edx 0x10)
 8153     #
 8154     (write _test-input-stream "fn foo {\n")
 8155     (write _test-input-stream "  copy-to\n")
 8156     (write _test-input-stream "}\n")
 8157     # convert
 8158     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8159     # registers except esp clobbered at this point
 8160     # restore ed
 8161     89/<- %edx 4/r32/esp
 8162     (flush _test-output-buffered-file)
 8163     (flush _test-error-buffered-file)
 8164 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8170     # check output
 8171     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 8172     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-inout: error message")
 8173     # check that stop(1) was called
 8174     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 8175     # don't restore from ebp
 8176     81 0/subop/add %esp 8/imm32
 8177     # . epilogue
 8178     5d/pop-to-ebp
 8179     c3/return
 8180 
 8181 test-copy-to-with-no-source:
 8182     # . prologue
 8183     55/push-ebp
 8184     89/<- %ebp 4/r32/esp
 8185     # setup
 8186     (clear-stream _test-input-stream)
 8187     (clear-stream $_test-input-buffered-file->buffer)
 8188     (clear-stream _test-output-stream)
 8189     (clear-stream $_test-output-buffered-file->buffer)
 8190     (clear-stream _test-error-stream)
 8191     (clear-stream $_test-error-buffered-file->buffer)
 8192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8193     68/push 0/imm32
 8194     68/push 0/imm32
 8195     89/<- %edx 4/r32/esp
 8196     (tailor-exit-descriptor %edx 0x10)
 8197     #
 8198     (write _test-input-stream "fn foo {\n")
 8199     (write _test-input-stream "  var x: boolean\n")
 8200     (write _test-input-stream "  copy-to x\n")
 8201     (write _test-input-stream "}\n")
 8202     # convert
 8203     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8204     # registers except esp clobbered at this point
 8205     # restore ed
 8206     89/<- %edx 4/r32/esp
 8207     (flush _test-output-buffered-file)
 8208     (flush _test-error-buffered-file)
 8209 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8215     # check output
 8216     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
 8217     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-source: error message")
 8218     # check that stop(1) was called
 8219     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
 8220     # don't restore from ebp
 8221     81 0/subop/add %esp 8/imm32
 8222     # . epilogue
 8223     5d/pop-to-ebp
 8224     c3/return
 8225 
 8226 test-copy-to-with-no-register:
 8227     # . prologue
 8228     55/push-ebp
 8229     89/<- %ebp 4/r32/esp
 8230     # setup
 8231     (clear-stream _test-input-stream)
 8232     (clear-stream $_test-input-buffered-file->buffer)
 8233     (clear-stream _test-output-stream)
 8234     (clear-stream $_test-output-buffered-file->buffer)
 8235     (clear-stream _test-error-stream)
 8236     (clear-stream $_test-error-buffered-file->buffer)
 8237     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8238     68/push 0/imm32
 8239     68/push 0/imm32
 8240     89/<- %edx 4/r32/esp
 8241     (tailor-exit-descriptor %edx 0x10)
 8242     #
 8243     (write _test-input-stream "fn foo {\n")
 8244     (write _test-input-stream "  var x: boolean\n")
 8245     (write _test-input-stream "  copy-to x, x\n")
 8246     (write _test-input-stream "}\n")
 8247     # convert
 8248     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8249     # registers except esp clobbered at this point
 8250     # restore ed
 8251     89/<- %edx 4/r32/esp
 8252     (flush _test-output-buffered-file)
 8253     (flush _test-error-buffered-file)
 8254 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8260     # check output
 8261     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 8262     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-with-no-register: error message")
 8263     # check that stop(1) was called
 8264     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 8265     # don't restore from ebp
 8266     81 0/subop/add %esp 8/imm32
 8267     # . epilogue
 8268     5d/pop-to-ebp
 8269     c3/return
 8270 
 8271 test-copy-to-with-too-many-inouts:
 8272     # . prologue
 8273     55/push-ebp
 8274     89/<- %ebp 4/r32/esp
 8275     # setup
 8276     (clear-stream _test-input-stream)
 8277     (clear-stream $_test-input-buffered-file->buffer)
 8278     (clear-stream _test-output-stream)
 8279     (clear-stream $_test-output-buffered-file->buffer)
 8280     (clear-stream _test-error-stream)
 8281     (clear-stream $_test-error-buffered-file->buffer)
 8282     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8283     68/push 0/imm32
 8284     68/push 0/imm32
 8285     89/<- %edx 4/r32/esp
 8286     (tailor-exit-descriptor %edx 0x10)
 8287     #
 8288     (write _test-input-stream "fn foo {\n")
 8289     (write _test-input-stream "  var x: boolean\n")
 8290     (write _test-input-stream "  copy-to x, 0, 0\n")
 8291     (write _test-input-stream "}\n")
 8292     # convert
 8293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8294     # registers except esp clobbered at this point
 8295     # restore ed
 8296     89/<- %edx 4/r32/esp
 8297     (flush _test-output-buffered-file)
 8298     (flush _test-error-buffered-file)
 8299 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8305     # check output
 8306     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 8307     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-too-many-inouts: error message")
 8308     # check that stop(1) was called
 8309     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 8310     # don't restore from ebp
 8311     81 0/subop/add %esp 8/imm32
 8312     # . epilogue
 8313     5d/pop-to-ebp
 8314     c3/return
 8315 
 8316 test-copy-to-with-output:
 8317     # . prologue
 8318     55/push-ebp
 8319     89/<- %ebp 4/r32/esp
 8320     # setup
 8321     (clear-stream _test-input-stream)
 8322     (clear-stream $_test-input-buffered-file->buffer)
 8323     (clear-stream _test-output-stream)
 8324     (clear-stream $_test-output-buffered-file->buffer)
 8325     (clear-stream _test-error-stream)
 8326     (clear-stream $_test-error-buffered-file->buffer)
 8327     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8328     68/push 0/imm32
 8329     68/push 0/imm32
 8330     89/<- %edx 4/r32/esp
 8331     (tailor-exit-descriptor %edx 0x10)
 8332     #
 8333     (write _test-input-stream "fn foo {\n")
 8334     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8335     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8336     (write _test-input-stream "  x <- copy-to y, 0\n")
 8337     (write _test-input-stream "}\n")
 8338     # convert
 8339     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8340     # registers except esp clobbered at this point
 8341     # restore ed
 8342     89/<- %edx 4/r32/esp
 8343     (flush _test-output-buffered-file)
 8344     (flush _test-error-buffered-file)
 8345 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8351     # check output
 8352     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 8353     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must not have any outputs"  "F - test-copy-to-with-output: error message")
 8354     # check that stop(1) was called
 8355     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 8356     # don't restore from ebp
 8357     81 0/subop/add %esp 8/imm32
 8358     # . epilogue
 8359     5d/pop-to-ebp
 8360     c3/return
 8361 
 8362 test-copy-to-invalid-value-to-address:
 8363     # . prologue
 8364     55/push-ebp
 8365     89/<- %ebp 4/r32/esp
 8366     # setup
 8367     (clear-stream _test-input-stream)
 8368     (clear-stream $_test-input-buffered-file->buffer)
 8369     (clear-stream _test-output-stream)
 8370     (clear-stream $_test-output-buffered-file->buffer)
 8371     (clear-stream _test-error-stream)
 8372     (clear-stream $_test-error-buffered-file->buffer)
 8373     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8374     68/push 0/imm32
 8375     68/push 0/imm32
 8376     89/<- %edx 4/r32/esp
 8377     (tailor-exit-descriptor %edx 0x10)
 8378     #
 8379     (write _test-input-stream "fn foo {\n")
 8380     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8381     (write _test-input-stream "  var y: (addr int)\n")
 8382     (write _test-input-stream "  copy-to y, x\n")
 8383     (write _test-input-stream "}\n")
 8384     # convert
 8385     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8386     # registers except esp clobbered at this point
 8387     # restore ed
 8388     89/<- %edx 4/r32/esp
 8389     (flush _test-output-buffered-file)
 8390     (flush _test-error-buffered-file)
 8391 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8397     # check output
 8398     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8399     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-address: error message")
 8400     # check that stop(1) was called
 8401     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8402     # don't restore from ebp
 8403     81 0/subop/add %esp 8/imm32
 8404     # . epilogue
 8405     5d/pop-to-ebp
 8406     c3/return
 8407 
 8408 test-copy-to-null-value-to-address:
 8409     # . prologue
 8410     55/push-ebp
 8411     89/<- %ebp 4/r32/esp
 8412     # setup
 8413     (clear-stream _test-input-stream)
 8414     (clear-stream $_test-input-buffered-file->buffer)
 8415     (clear-stream _test-output-stream)
 8416     (clear-stream $_test-output-buffered-file->buffer)
 8417     #
 8418     (write _test-input-stream "fn foo {\n")
 8419     (write _test-input-stream "  var y: (addr int)\n")
 8420     (write _test-input-stream "  copy-to y, 0\n")
 8421     (write _test-input-stream "}\n")
 8422     # convert
 8423     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8424     (flush _test-output-buffered-file)
 8425     # no errors
 8426     # . epilogue
 8427     89/<- %esp 5/r32/ebp
 8428     5d/pop-to-ebp
 8429     c3/return
 8430 
 8431 test-copy-to-invalid-value-to-offset:
 8432     # . prologue
 8433     55/push-ebp
 8434     89/<- %ebp 4/r32/esp
 8435     # setup
 8436     (clear-stream _test-input-stream)
 8437     (clear-stream $_test-input-buffered-file->buffer)
 8438     (clear-stream _test-output-stream)
 8439     (clear-stream $_test-output-buffered-file->buffer)
 8440     (clear-stream _test-error-stream)
 8441     (clear-stream $_test-error-buffered-file->buffer)
 8442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8443     68/push 0/imm32
 8444     68/push 0/imm32
 8445     89/<- %edx 4/r32/esp
 8446     (tailor-exit-descriptor %edx 0x10)
 8447     #
 8448     (write _test-input-stream "fn foo {\n")
 8449     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8450     (write _test-input-stream "  var y: (offset int)\n")
 8451     (write _test-input-stream "  copy-to y, x\n")
 8452     (write _test-input-stream "}\n")
 8453     # convert
 8454     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8455     # registers except esp clobbered at this point
 8456     # restore ed
 8457     89/<- %edx 4/r32/esp
 8458     (flush _test-output-buffered-file)
 8459     (flush _test-error-buffered-file)
 8460 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8466     # check output
 8467     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
 8468     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-offset: error message")
 8469     # check that stop(1) was called
 8470     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
 8471     # don't restore from ebp
 8472     81 0/subop/add %esp 8/imm32
 8473     # . epilogue
 8474     5d/pop-to-ebp
 8475     c3/return
 8476 
 8477 test-copy-to-null-value-to-offset:
 8478     # . prologue
 8479     55/push-ebp
 8480     89/<- %ebp 4/r32/esp
 8481     # setup
 8482     (clear-stream _test-input-stream)
 8483     (clear-stream $_test-input-buffered-file->buffer)
 8484     (clear-stream _test-output-stream)
 8485     (clear-stream $_test-output-buffered-file->buffer)
 8486     #
 8487     (write _test-input-stream "fn foo {\n")
 8488     (write _test-input-stream "  var y: (offset int)\n")
 8489     (write _test-input-stream "  copy-to y, 0\n")
 8490     (write _test-input-stream "}\n")
 8491     # convert
 8492     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8493     (flush _test-output-buffered-file)
 8494     # no errors
 8495     # . epilogue
 8496     89/<- %esp 5/r32/ebp
 8497     5d/pop-to-ebp
 8498     c3/return
 8499 
 8500 test-copy-to-non-literal-to-byte:
 8501     # . prologue
 8502     55/push-ebp
 8503     89/<- %ebp 4/r32/esp
 8504     # setup
 8505     (clear-stream _test-input-stream)
 8506     (clear-stream $_test-input-buffered-file->buffer)
 8507     (clear-stream _test-output-stream)
 8508     (clear-stream $_test-output-buffered-file->buffer)
 8509     (clear-stream _test-error-stream)
 8510     (clear-stream $_test-error-buffered-file->buffer)
 8511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8512     68/push 0/imm32
 8513     68/push 0/imm32
 8514     89/<- %edx 4/r32/esp
 8515     (tailor-exit-descriptor %edx 0x10)
 8516     #
 8517     (write _test-input-stream "fn foo {\n")
 8518     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
 8519     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 8520     (write _test-input-stream "  copy-to *y, x\n")
 8521     (write _test-input-stream "}\n")
 8522     # convert
 8523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8524     # registers except esp clobbered at this point
 8525     # restore ed
 8526     89/<- %edx 4/r32/esp
 8527     (flush _test-output-buffered-file)
 8528     (flush _test-error-buffered-file)
 8529 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8535     # check output
 8536     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
 8537     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to"  "F - test-copy-to-non-literal-to-byte: error message")
 8538     # check that stop(1) was called
 8539     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
 8540     # don't restore from ebp
 8541     81 0/subop/add %esp 8/imm32
 8542     # . epilogue
 8543     5d/pop-to-ebp
 8544     c3/return
 8545 
 8546 test-copy-to-deref-address:
 8547     # . prologue
 8548     55/push-ebp
 8549     89/<- %ebp 4/r32/esp
 8550     # setup
 8551     (clear-stream _test-input-stream)
 8552     (clear-stream $_test-input-buffered-file->buffer)
 8553     (clear-stream _test-output-stream)
 8554     (clear-stream $_test-output-buffered-file->buffer)
 8555     #
 8556     (write _test-input-stream "fn foo {\n")
 8557     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8558     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8559     (write _test-input-stream "  copy-to *y, x\n")
 8560     (write _test-input-stream "}\n")
 8561     # convert
 8562     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8563     (flush _test-output-buffered-file)
 8564     # no errors
 8565     # . epilogue
 8566     5d/pop-to-ebp
 8567     c3/return
 8568 
 8569 test-copy-to-from-non-scalar-inout:
 8570     # . prologue
 8571     55/push-ebp
 8572     89/<- %ebp 4/r32/esp
 8573     # setup
 8574     (clear-stream _test-input-stream)
 8575     (clear-stream $_test-input-buffered-file->buffer)
 8576     (clear-stream _test-output-stream)
 8577     (clear-stream $_test-output-buffered-file->buffer)
 8578     (clear-stream _test-error-stream)
 8579     (clear-stream $_test-error-buffered-file->buffer)
 8580     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8581     68/push 0/imm32
 8582     68/push 0/imm32
 8583     89/<- %edx 4/r32/esp
 8584     (tailor-exit-descriptor %edx 0x10)
 8585     #
 8586     (write _test-input-stream "fn foo {\n")
 8587     (write _test-input-stream "  var x: (handle int)\n")
 8588     (write _test-input-stream "  var y: int\n")
 8589     (write _test-input-stream "  copy-to y, x\n")
 8590     (write _test-input-stream "}\n")
 8591     # convert
 8592     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8593     # registers except esp clobbered at this point
 8594     # restore ed
 8595     89/<- %edx 4/r32/esp
 8596     (flush _test-output-buffered-file)
 8597     (flush _test-error-buffered-file)
 8598 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8604     # check output
 8605     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
 8606     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-from-non-scalar-inout: error message")
 8607     # check that stop(1) was called
 8608     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
 8609     # don't restore from ebp
 8610     81 0/subop/add %esp 8/imm32
 8611     # . epilogue
 8612     5d/pop-to-ebp
 8613     c3/return
 8614 
 8615 test-copy-byte-with-no-inout:
 8616     # . prologue
 8617     55/push-ebp
 8618     89/<- %ebp 4/r32/esp
 8619     # setup
 8620     (clear-stream _test-input-stream)
 8621     (clear-stream $_test-input-buffered-file->buffer)
 8622     (clear-stream _test-output-stream)
 8623     (clear-stream $_test-output-buffered-file->buffer)
 8624     (clear-stream _test-error-stream)
 8625     (clear-stream $_test-error-buffered-file->buffer)
 8626     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8627     68/push 0/imm32
 8628     68/push 0/imm32
 8629     89/<- %edx 4/r32/esp
 8630     (tailor-exit-descriptor %edx 0x10)
 8631     #
 8632     (write _test-input-stream "fn foo {\n")
 8633     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
 8634     (write _test-input-stream "}\n")
 8635     # convert
 8636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8637     # registers except esp clobbered at this point
 8638     # restore ed
 8639     89/<- %edx 4/r32/esp
 8640     (flush _test-output-buffered-file)
 8641     (flush _test-error-buffered-file)
 8642 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8648     # check output
 8649     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
 8650     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an inout"  "F - test-copy-byte-with-no-inout: error message")
 8651     # check that stop(1) was called
 8652     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
 8653     # don't restore from ebp
 8654     81 0/subop/add %esp 8/imm32
 8655     # . epilogue
 8656     5d/pop-to-ebp
 8657     c3/return
 8658 
 8659 test-copy-byte-with-multiple-inouts:
 8660     # . prologue
 8661     55/push-ebp
 8662     89/<- %ebp 4/r32/esp
 8663     # setup
 8664     (clear-stream _test-input-stream)
 8665     (clear-stream $_test-input-buffered-file->buffer)
 8666     (clear-stream _test-output-stream)
 8667     (clear-stream $_test-output-buffered-file->buffer)
 8668     (clear-stream _test-error-stream)
 8669     (clear-stream $_test-error-buffered-file->buffer)
 8670     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8671     68/push 0/imm32
 8672     68/push 0/imm32
 8673     89/<- %edx 4/r32/esp
 8674     (tailor-exit-descriptor %edx 0x10)
 8675     #
 8676     (write _test-input-stream "fn foo {\n")
 8677     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
 8678     (write _test-input-stream "}\n")
 8679     # convert
 8680     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8681     # registers except esp clobbered at this point
 8682     # restore ed
 8683     89/<- %edx 4/r32/esp
 8684     (flush _test-output-buffered-file)
 8685     (flush _test-error-buffered-file)
 8686 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8692     # check output
 8693     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
 8694     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one inout"  "F - test-copy-byte-with-multiple-inouts: error message")
 8695     # check that stop(1) was called
 8696     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
 8697     # don't restore from ebp
 8698     81 0/subop/add %esp 8/imm32
 8699     # . epilogue
 8700     5d/pop-to-ebp
 8701     c3/return
 8702 
 8703 test-copy-byte-with-no-output:
 8704     # . prologue
 8705     55/push-ebp
 8706     89/<- %ebp 4/r32/esp
 8707     # setup
 8708     (clear-stream _test-input-stream)
 8709     (clear-stream $_test-input-buffered-file->buffer)
 8710     (clear-stream _test-output-stream)
 8711     (clear-stream $_test-output-buffered-file->buffer)
 8712     (clear-stream _test-error-stream)
 8713     (clear-stream $_test-error-buffered-file->buffer)
 8714     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8715     68/push 0/imm32
 8716     68/push 0/imm32
 8717     89/<- %edx 4/r32/esp
 8718     (tailor-exit-descriptor %edx 0x10)
 8719     #
 8720     (write _test-input-stream "fn foo {\n")
 8721     (write _test-input-stream "  copy-byte 0\n")
 8722     (write _test-input-stream "}\n")
 8723     # convert
 8724     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8725     # registers except esp clobbered at this point
 8726     # restore ed
 8727     89/<- %edx 4/r32/esp
 8728     (flush _test-output-buffered-file)
 8729     (flush _test-error-buffered-file)
 8730 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8736     # check output
 8737     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
 8738     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an output"  "F - test-copy-byte-with-no-output: error message")
 8739     # check that stop(1) was called
 8740     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
 8741     # don't restore from ebp
 8742     81 0/subop/add %esp 8/imm32
 8743     # . epilogue
 8744     5d/pop-to-ebp
 8745     c3/return
 8746 
 8747 test-copy-byte-with-multiple-outputs:
 8748     # . prologue
 8749     55/push-ebp
 8750     89/<- %ebp 4/r32/esp
 8751     # setup
 8752     (clear-stream _test-input-stream)
 8753     (clear-stream $_test-input-buffered-file->buffer)
 8754     (clear-stream _test-output-stream)
 8755     (clear-stream $_test-output-buffered-file->buffer)
 8756     (clear-stream _test-error-stream)
 8757     (clear-stream $_test-error-buffered-file->buffer)
 8758     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8759     68/push 0/imm32
 8760     68/push 0/imm32
 8761     89/<- %edx 4/r32/esp
 8762     (tailor-exit-descriptor %edx 0x10)
 8763     #
 8764     (write _test-input-stream "fn foo {\n")
 8765     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 8766     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 8767     (write _test-input-stream "  x, y <- copy-byte 0\n")
 8768     (write _test-input-stream "}\n")
 8769     # convert
 8770     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8771     # registers except esp clobbered at this point
 8772     # restore ed
 8773     89/<- %edx 4/r32/esp
 8774     (flush _test-output-buffered-file)
 8775     (flush _test-error-buffered-file)
 8776 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8782     # check output
 8783     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
 8784     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one output"  "F - test-copy-byte-with-multiple-outputs: error message")
 8785     # check that stop(1) was called
 8786     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
 8787     # don't restore from ebp
 8788     81 0/subop/add %esp 8/imm32
 8789     # . epilogue
 8790     5d/pop-to-ebp
 8791     c3/return
 8792 
 8793 test-copy-byte-deref-address:
 8794     # . prologue
 8795     55/push-ebp
 8796     89/<- %ebp 4/r32/esp
 8797     # setup
 8798     (clear-stream _test-input-stream)
 8799     (clear-stream $_test-input-buffered-file->buffer)
 8800     (clear-stream _test-output-stream)
 8801     (clear-stream $_test-output-buffered-file->buffer)
 8802     #
 8803     (write _test-input-stream "fn foo {\n")
 8804     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8805     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
 8806     (write _test-input-stream "}\n")
 8807     # convert
 8808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8809     (flush _test-output-buffered-file)
 8810 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8816     # not bothering checking output
 8817     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
 8818     # . epilogue
 8819     5d/pop-to-ebp
 8820     c3/return
 8821 
 8822 test-copy-byte-with-invalid-output-type:
 8823     # . prologue
 8824     55/push-ebp
 8825     89/<- %ebp 4/r32/esp
 8826     # setup
 8827     (clear-stream _test-input-stream)
 8828     (clear-stream $_test-input-buffered-file->buffer)
 8829     (clear-stream _test-output-stream)
 8830     (clear-stream $_test-output-buffered-file->buffer)
 8831     (clear-stream _test-error-stream)
 8832     (clear-stream $_test-error-buffered-file->buffer)
 8833     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8834     68/push 0/imm32
 8835     68/push 0/imm32
 8836     89/<- %edx 4/r32/esp
 8837     (tailor-exit-descriptor %edx 0x10)
 8838     #
 8839     (write _test-input-stream "fn foo {\n")
 8840     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8841     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
 8842     (write _test-input-stream "}\n")
 8843     # convert
 8844     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8845     # registers except esp clobbered at this point
 8846     # restore ed
 8847     89/<- %edx 4/r32/esp
 8848     (flush _test-output-buffered-file)
 8849     (flush _test-error-buffered-file)
 8850 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8856     # check output
 8857     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
 8858     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must write to output of type byte"  "F - test-copy-byte-with-invalid-output-type: error message")
 8859     # check that stop(1) was called
 8860     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
 8861     # don't restore from ebp
 8862     81 0/subop/add %esp 8/imm32
 8863     # . epilogue
 8864     5d/pop-to-ebp
 8865     c3/return
 8866 
 8867 test-copy-byte-from-non-scalar-inout:
 8868     # . prologue
 8869     55/push-ebp
 8870     89/<- %ebp 4/r32/esp
 8871     # setup
 8872     (clear-stream _test-input-stream)
 8873     (clear-stream $_test-input-buffered-file->buffer)
 8874     (clear-stream _test-output-stream)
 8875     (clear-stream $_test-output-buffered-file->buffer)
 8876     (clear-stream _test-error-stream)
 8877     (clear-stream $_test-error-buffered-file->buffer)
 8878     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8879     68/push 0/imm32
 8880     68/push 0/imm32
 8881     89/<- %edx 4/r32/esp
 8882     (tailor-exit-descriptor %edx 0x10)
 8883     #
 8884     (write _test-input-stream "fn foo {\n")
 8885     (write _test-input-stream "  var x: (handle int)\n")
 8886     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
 8887     (write _test-input-stream "}\n")
 8888     # convert
 8889     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8890     # registers except esp clobbered at this point
 8891     # restore ed
 8892     89/<- %edx 4/r32/esp
 8893     (flush _test-output-buffered-file)
 8894     (flush _test-error-buffered-file)
 8895 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8901     # check output
 8902     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
 8903     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: 'x' is too large to fit in a register"  "F - test-copy-byte-from-non-scalar-inout: error message")
 8904     # check that stop(1) was called
 8905     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
 8906     # don't restore from ebp
 8907     81 0/subop/add %esp 8/imm32
 8908     # . epilogue
 8909     5d/pop-to-ebp
 8910     c3/return
 8911 
 8912 test-copy-byte-to-with-no-inout:
 8913     # . prologue
 8914     55/push-ebp
 8915     89/<- %ebp 4/r32/esp
 8916     # setup
 8917     (clear-stream _test-input-stream)
 8918     (clear-stream $_test-input-buffered-file->buffer)
 8919     (clear-stream _test-output-stream)
 8920     (clear-stream $_test-output-buffered-file->buffer)
 8921     (clear-stream _test-error-stream)
 8922     (clear-stream $_test-error-buffered-file->buffer)
 8923     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8924     68/push 0/imm32
 8925     68/push 0/imm32
 8926     89/<- %edx 4/r32/esp
 8927     (tailor-exit-descriptor %edx 0x10)
 8928     #
 8929     (write _test-input-stream "fn foo {\n")
 8930     (write _test-input-stream "  copy-byte-to\n")
 8931     (write _test-input-stream "}\n")
 8932     # convert
 8933     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8934     # registers except esp clobbered at this point
 8935     # restore ed
 8936     89/<- %edx 4/r32/esp
 8937     (flush _test-output-buffered-file)
 8938     (flush _test-error-buffered-file)
 8939 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8945     # check output
 8946     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
 8947     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-inout: error message")
 8948     # check that stop(1) was called
 8949     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
 8950     # don't restore from ebp
 8951     81 0/subop/add %esp 8/imm32
 8952     # . epilogue
 8953     5d/pop-to-ebp
 8954     c3/return
 8955 
 8956 test-copy-byte-to-with-no-source:
 8957     # . prologue
 8958     55/push-ebp
 8959     89/<- %ebp 4/r32/esp
 8960     # setup
 8961     (clear-stream _test-input-stream)
 8962     (clear-stream $_test-input-buffered-file->buffer)
 8963     (clear-stream _test-output-stream)
 8964     (clear-stream $_test-output-buffered-file->buffer)
 8965     (clear-stream _test-error-stream)
 8966     (clear-stream $_test-error-buffered-file->buffer)
 8967     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8968     68/push 0/imm32
 8969     68/push 0/imm32
 8970     89/<- %edx 4/r32/esp
 8971     (tailor-exit-descriptor %edx 0x10)
 8972     #
 8973     (write _test-input-stream "fn foo {\n")
 8974     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 8975     (write _test-input-stream "  copy-byte-to *x\n")
 8976     (write _test-input-stream "}\n")
 8977     # convert
 8978     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8979     # registers except esp clobbered at this point
 8980     # restore ed
 8981     89/<- %edx 4/r32/esp
 8982     (flush _test-output-buffered-file)
 8983     (flush _test-error-buffered-file)
 8984 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 8990     # check output
 8991     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
 8992     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-source: error message")
 8993     # check that stop(1) was called
 8994     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
 8995     # don't restore from ebp
 8996     81 0/subop/add %esp 8/imm32
 8997     # . epilogue
 8998     5d/pop-to-ebp
 8999     c3/return
 9000 
 9001 test-copy-byte-to-with-too-many-inouts:
 9002     # . prologue
 9003     55/push-ebp
 9004     89/<- %ebp 4/r32/esp
 9005     # setup
 9006     (clear-stream _test-input-stream)
 9007     (clear-stream $_test-input-buffered-file->buffer)
 9008     (clear-stream _test-output-stream)
 9009     (clear-stream $_test-output-buffered-file->buffer)
 9010     (clear-stream _test-error-stream)
 9011     (clear-stream $_test-error-buffered-file->buffer)
 9012     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9013     68/push 0/imm32
 9014     68/push 0/imm32
 9015     89/<- %edx 4/r32/esp
 9016     (tailor-exit-descriptor %edx 0x10)
 9017     #
 9018     (write _test-input-stream "fn foo {\n")
 9019     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9020     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
 9021     (write _test-input-stream "}\n")
 9022     # convert
 9023     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9024     # registers except esp clobbered at this point
 9025     # restore ed
 9026     89/<- %edx 4/r32/esp
 9027     (flush _test-output-buffered-file)
 9028     (flush _test-error-buffered-file)
 9029 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9035     # check output
 9036     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
 9037     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-too-many-inouts: error message")
 9038     # check that stop(1) was called
 9039     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
 9040     # don't restore from ebp
 9041     81 0/subop/add %esp 8/imm32
 9042     # . epilogue
 9043     5d/pop-to-ebp
 9044     c3/return
 9045 
 9046 test-copy-byte-to-with-output:
 9047     # . prologue
 9048     55/push-ebp
 9049     89/<- %ebp 4/r32/esp
 9050     # setup
 9051     (clear-stream _test-input-stream)
 9052     (clear-stream $_test-input-buffered-file->buffer)
 9053     (clear-stream _test-output-stream)
 9054     (clear-stream $_test-output-buffered-file->buffer)
 9055     (clear-stream _test-error-stream)
 9056     (clear-stream $_test-error-buffered-file->buffer)
 9057     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9058     68/push 0/imm32
 9059     68/push 0/imm32
 9060     89/<- %edx 4/r32/esp
 9061     (tailor-exit-descriptor %edx 0x10)
 9062     #
 9063     (write _test-input-stream "fn foo {\n")
 9064     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9065     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9066     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
 9067     (write _test-input-stream "}\n")
 9068     # convert
 9069     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9070     # registers except esp clobbered at this point
 9071     # restore ed
 9072     89/<- %edx 4/r32/esp
 9073     (flush _test-output-buffered-file)
 9074     (flush _test-error-buffered-file)
 9075 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9081     # check output
 9082     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
 9083     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must not have any outputs"  "F - test-copy-byte-to-with-output: error message")
 9084     # check that stop(1) was called
 9085     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
 9086     # don't restore from ebp
 9087     81 0/subop/add %esp 8/imm32
 9088     # . epilogue
 9089     5d/pop-to-ebp
 9090     c3/return
 9091 
 9092 test-copy-byte-to-with-invalid-output-type:
 9093     # . prologue
 9094     55/push-ebp
 9095     89/<- %ebp 4/r32/esp
 9096     # setup
 9097     (clear-stream _test-input-stream)
 9098     (clear-stream $_test-input-buffered-file->buffer)
 9099     (clear-stream _test-output-stream)
 9100     (clear-stream $_test-output-buffered-file->buffer)
 9101     (clear-stream _test-error-stream)
 9102     (clear-stream $_test-error-buffered-file->buffer)
 9103     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9104     68/push 0/imm32
 9105     68/push 0/imm32
 9106     89/<- %edx 4/r32/esp
 9107     (tailor-exit-descriptor %edx 0x10)
 9108     #
 9109     (write _test-input-stream "fn foo {\n")
 9110     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9111     (write _test-input-stream "  var y: int\n")
 9112     (write _test-input-stream "  copy-byte-to y, x\n")
 9113     (write _test-input-stream "}\n")
 9114     # convert
 9115     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9116     # registers except esp clobbered at this point
 9117     # restore ed
 9118     89/<- %edx 4/r32/esp
 9119     (flush _test-output-buffered-file)
 9120     (flush _test-error-buffered-file)
 9121 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9127     # check output
 9128     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
 9129     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'y' must be a byte"  "F - test-copy-byte-to-with-invalid-output-type: error message")
 9130     # check that stop(1) was called
 9131     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
 9132     # don't restore from ebp
 9133     81 0/subop/add %esp 8/imm32
 9134     # . epilogue
 9135     5d/pop-to-ebp
 9136     c3/return
 9137 
 9138 test-copy-byte-to-with-literal-inout:
 9139     # . prologue
 9140     55/push-ebp
 9141     89/<- %ebp 4/r32/esp
 9142     # setup
 9143     (clear-stream _test-input-stream)
 9144     (clear-stream $_test-input-buffered-file->buffer)
 9145     (clear-stream _test-output-stream)
 9146     (clear-stream $_test-output-buffered-file->buffer)
 9147     (clear-stream _test-error-stream)
 9148     (clear-stream $_test-error-buffered-file->buffer)
 9149     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9150     68/push 0/imm32
 9151     68/push 0/imm32
 9152     89/<- %edx 4/r32/esp
 9153     (tailor-exit-descriptor %edx 0x10)
 9154     #
 9155     (write _test-input-stream "fn foo {\n")
 9156     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
 9157     (write _test-input-stream "  copy-byte-to *x, 0\n")
 9158     (write _test-input-stream "}\n")
 9159     # convert
 9160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9161     # registers except esp clobbered at this point
 9162     # restore ed
 9163     89/<- %edx 4/r32/esp
 9164     (flush _test-output-buffered-file)
 9165     (flush _test-error-buffered-file)
 9166 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9172     # check output
 9173     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
 9174     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must be in a register"  "F - test-copy-byte-to-with-literal-inout: error message")
 9175     # check that stop(1) was called
 9176     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
 9177     # don't restore from ebp
 9178     81 0/subop/add %esp 8/imm32
 9179     # . epilogue
 9180     5d/pop-to-ebp
 9181     c3/return
 9182 
 9183 test-copy-byte-to-deref-address:
 9184     # . prologue
 9185     55/push-ebp
 9186     89/<- %ebp 4/r32/esp
 9187     # setup
 9188     (clear-stream _test-input-stream)
 9189     (clear-stream $_test-input-buffered-file->buffer)
 9190     (clear-stream _test-output-stream)
 9191     (clear-stream $_test-output-buffered-file->buffer)
 9192     #
 9193     (write _test-input-stream "fn foo {\n")
 9194     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 9195     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
 9196     (write _test-input-stream "  copy-byte-to *y, x\n")
 9197     (write _test-input-stream "}\n")
 9198     # convert
 9199     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9200     (flush _test-output-buffered-file)
 9201     # no errors
 9202     # . epilogue
 9203     5d/pop-to-ebp
 9204     c3/return
 9205 
 9206 test-copy-byte-to-from-non-scalar-inout:
 9207     # . prologue
 9208     55/push-ebp
 9209     89/<- %ebp 4/r32/esp
 9210     # setup
 9211     (clear-stream _test-input-stream)
 9212     (clear-stream $_test-input-buffered-file->buffer)
 9213     (clear-stream _test-output-stream)
 9214     (clear-stream $_test-output-buffered-file->buffer)
 9215     (clear-stream _test-error-stream)
 9216     (clear-stream $_test-error-buffered-file->buffer)
 9217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9218     68/push 0/imm32
 9219     68/push 0/imm32
 9220     89/<- %edx 4/r32/esp
 9221     (tailor-exit-descriptor %edx 0x10)
 9222     #
 9223     (write _test-input-stream "fn foo {\n")
 9224     (write _test-input-stream "  var x: (handle int)\n")
 9225     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
 9226     (write _test-input-stream "  copy-byte-to *y, x\n")
 9227     (write _test-input-stream "}\n")
 9228     # convert
 9229     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9230     # registers except esp clobbered at this point
 9231     # restore ed
 9232     89/<- %edx 4/r32/esp
 9233     (flush _test-output-buffered-file)
 9234     (flush _test-error-buffered-file)
 9235 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9241     # check output
 9242     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
 9243     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
 9244     # check that stop(1) was called
 9245     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
 9246     # don't restore from ebp
 9247     81 0/subop/add %esp 8/imm32
 9248     # . epilogue
 9249     5d/pop-to-ebp
 9250     c3/return
 9251 
 9252 test-compare-with-no-inout:
 9253     # . prologue
 9254     55/push-ebp
 9255     89/<- %ebp 4/r32/esp
 9256     # setup
 9257     (clear-stream _test-input-stream)
 9258     (clear-stream $_test-input-buffered-file->buffer)
 9259     (clear-stream _test-output-stream)
 9260     (clear-stream $_test-output-buffered-file->buffer)
 9261     (clear-stream _test-error-stream)
 9262     (clear-stream $_test-error-buffered-file->buffer)
 9263     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9264     68/push 0/imm32
 9265     68/push 0/imm32
 9266     89/<- %edx 4/r32/esp
 9267     (tailor-exit-descriptor %edx 0x10)
 9268     #
 9269     (write _test-input-stream "fn foo {\n")
 9270     (write _test-input-stream "  var x: boolean\n")
 9271     (write _test-input-stream "  compare\n")
 9272     (write _test-input-stream "}\n")
 9273     # convert
 9274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9275     # registers except esp clobbered at this point
 9276     # restore ed
 9277     89/<- %edx 4/r32/esp
 9278     (flush _test-output-buffered-file)
 9279     (flush _test-error-buffered-file)
 9280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9286     # check output
 9287     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 9288     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 9289     # check that stop(1) was called
 9290     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 9291     # don't restore from ebp
 9292     81 0/subop/add %esp 8/imm32
 9293     # . epilogue
 9294     5d/pop-to-ebp
 9295     c3/return
 9296 
 9297 test-compare-with-just-one-inout:
 9298     # . prologue
 9299     55/push-ebp
 9300     89/<- %ebp 4/r32/esp
 9301     # setup
 9302     (clear-stream _test-input-stream)
 9303     (clear-stream $_test-input-buffered-file->buffer)
 9304     (clear-stream _test-output-stream)
 9305     (clear-stream $_test-output-buffered-file->buffer)
 9306     (clear-stream _test-error-stream)
 9307     (clear-stream $_test-error-buffered-file->buffer)
 9308     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9309     68/push 0/imm32
 9310     68/push 0/imm32
 9311     89/<- %edx 4/r32/esp
 9312     (tailor-exit-descriptor %edx 0x10)
 9313     #
 9314     (write _test-input-stream "fn foo {\n")
 9315     (write _test-input-stream "  var x: boolean\n")
 9316     (write _test-input-stream "  compare x\n")
 9317     (write _test-input-stream "}\n")
 9318     # convert
 9319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9320     # registers except esp clobbered at this point
 9321     # restore ed
 9322     89/<- %edx 4/r32/esp
 9323     (flush _test-output-buffered-file)
 9324     (flush _test-error-buffered-file)
 9325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9331     # check output
 9332     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
 9333     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-just-one-inout: error message")
 9334     # check that stop(1) was called
 9335     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
 9336     # don't restore from ebp
 9337     81 0/subop/add %esp 8/imm32
 9338     # . epilogue
 9339     5d/pop-to-ebp
 9340     c3/return
 9341 
 9342 test-compare-with-too-many-inouts:
 9343     # . prologue
 9344     55/push-ebp
 9345     89/<- %ebp 4/r32/esp
 9346     # setup
 9347     (clear-stream _test-input-stream)
 9348     (clear-stream $_test-input-buffered-file->buffer)
 9349     (clear-stream _test-output-stream)
 9350     (clear-stream $_test-output-buffered-file->buffer)
 9351     (clear-stream _test-error-stream)
 9352     (clear-stream $_test-error-buffered-file->buffer)
 9353     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9354     68/push 0/imm32
 9355     68/push 0/imm32
 9356     89/<- %edx 4/r32/esp
 9357     (tailor-exit-descriptor %edx 0x10)
 9358     #
 9359     (write _test-input-stream "fn foo {\n")
 9360     (write _test-input-stream "  var x: boolean\n")
 9361     (write _test-input-stream "  compare x, 0, 0\n")
 9362     (write _test-input-stream "}\n")
 9363     # convert
 9364     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9365     # registers except esp clobbered at this point
 9366     # restore ed
 9367     89/<- %edx 4/r32/esp
 9368     (flush _test-output-buffered-file)
 9369     (flush _test-error-buffered-file)
 9370 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9376     # check output
 9377     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 9378     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-too-many-inouts: error message")
 9379     # check that stop(1) was called
 9380     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 9381     # don't restore from ebp
 9382     81 0/subop/add %esp 8/imm32
 9383     # . epilogue
 9384     5d/pop-to-ebp
 9385     c3/return
 9386 
 9387 test-compare-with-output:
 9388     # . prologue
 9389     55/push-ebp
 9390     89/<- %ebp 4/r32/esp
 9391     # setup
 9392     (clear-stream _test-input-stream)
 9393     (clear-stream $_test-input-buffered-file->buffer)
 9394     (clear-stream _test-output-stream)
 9395     (clear-stream $_test-output-buffered-file->buffer)
 9396     (clear-stream _test-error-stream)
 9397     (clear-stream $_test-error-buffered-file->buffer)
 9398     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9399     68/push 0/imm32
 9400     68/push 0/imm32
 9401     89/<- %edx 4/r32/esp
 9402     (tailor-exit-descriptor %edx 0x10)
 9403     #
 9404     (write _test-input-stream "fn foo {\n")
 9405     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9406     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9407     (write _test-input-stream "  x <- compare y, 0\n")
 9408     (write _test-input-stream "}\n")
 9409     # convert
 9410     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9411     # registers except esp clobbered at this point
 9412     # restore ed
 9413     89/<- %edx 4/r32/esp
 9414     (flush _test-output-buffered-file)
 9415     (flush _test-error-buffered-file)
 9416 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9422     # check output
 9423     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 9424     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 9425     # check that stop(1) was called
 9426     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 9427     # don't restore from ebp
 9428     81 0/subop/add %esp 8/imm32
 9429     # . epilogue
 9430     5d/pop-to-ebp
 9431     c3/return
 9432 
 9433 test-compare-invalid-value-to-address:
 9434     # . prologue
 9435     55/push-ebp
 9436     89/<- %ebp 4/r32/esp
 9437     # setup
 9438     (clear-stream _test-input-stream)
 9439     (clear-stream $_test-input-buffered-file->buffer)
 9440     (clear-stream _test-output-stream)
 9441     (clear-stream $_test-output-buffered-file->buffer)
 9442     (clear-stream _test-error-stream)
 9443     (clear-stream $_test-error-buffered-file->buffer)
 9444     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9445     68/push 0/imm32
 9446     68/push 0/imm32
 9447     89/<- %edx 4/r32/esp
 9448     (tailor-exit-descriptor %edx 0x10)
 9449     #
 9450     (write _test-input-stream "fn foo {\n")
 9451     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 9452     (write _test-input-stream "  var y: (addr int)\n")
 9453     (write _test-input-stream "  compare y, x\n")
 9454     (write _test-input-stream "}\n")
 9455     # convert
 9456     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9457     # registers except esp clobbered at this point
 9458     # restore ed
 9459     89/<- %edx 4/r32/esp
 9460     (flush _test-output-buffered-file)
 9461     (flush _test-error-buffered-file)
 9462 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9468     # check output
 9469     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 9470     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar"  "F - test-compare-invalid-value-to-address: error message")
 9471     # check that stop(1) was called
 9472     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 9473     # don't restore from ebp
 9474     81 0/subop/add %esp 8/imm32
 9475     # . epilogue
 9476     5d/pop-to-ebp
 9477     c3/return
 9478 
 9479 test-compare-address:
 9480     # . prologue
 9481     55/push-ebp
 9482     89/<- %ebp 4/r32/esp
 9483     # setup
 9484     (clear-stream _test-input-stream)
 9485     (clear-stream $_test-input-buffered-file->buffer)
 9486     (clear-stream _test-output-stream)
 9487     (clear-stream $_test-output-buffered-file->buffer)
 9488     #
 9489     (write _test-input-stream "fn foo {\n")
 9490     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9491     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 9492     (write _test-input-stream "  compare y, x\n")
 9493     (write _test-input-stream "}\n")
 9494     # convert
 9495     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9496     (flush _test-output-buffered-file)
 9497     # no errors
 9498     # . epilogue
 9499     5d/pop-to-ebp
 9500     c3/return
 9501 
 9502 test-compare-deref-address:
 9503     # . prologue
 9504     55/push-ebp
 9505     89/<- %ebp 4/r32/esp
 9506     # setup
 9507     (clear-stream _test-input-stream)
 9508     (clear-stream $_test-input-buffered-file->buffer)
 9509     (clear-stream _test-output-stream)
 9510     (clear-stream $_test-output-buffered-file->buffer)
 9511     #
 9512     (write _test-input-stream "fn foo {\n")
 9513     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9514     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 9515     (write _test-input-stream "  compare *y, x\n")
 9516     (write _test-input-stream "}\n")
 9517     # convert
 9518     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9519     (flush _test-output-buffered-file)
 9520     # no errors
 9521     # . epilogue
 9522     5d/pop-to-ebp
 9523     c3/return
 9524 
 9525 test-compare-two-vars-in-memory:
 9526     # . prologue
 9527     55/push-ebp
 9528     89/<- %ebp 4/r32/esp
 9529     # setup
 9530     (clear-stream _test-input-stream)
 9531     (clear-stream $_test-input-buffered-file->buffer)
 9532     (clear-stream _test-output-stream)
 9533     (clear-stream $_test-output-buffered-file->buffer)
 9534     (clear-stream _test-error-stream)
 9535     (clear-stream $_test-error-buffered-file->buffer)
 9536     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9537     68/push 0/imm32
 9538     68/push 0/imm32
 9539     89/<- %edx 4/r32/esp
 9540     (tailor-exit-descriptor %edx 0x10)
 9541     #
 9542     (write _test-input-stream "fn foo {\n")
 9543     (write _test-input-stream "  var x: boolean\n")
 9544     (write _test-input-stream "  compare x, x\n")
 9545     (write _test-input-stream "}\n")
 9546     # convert
 9547     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9548     # registers except esp clobbered at this point
 9549     # restore ed
 9550     89/<- %edx 4/r32/esp
 9551     (flush _test-output-buffered-file)
 9552     (flush _test-error-buffered-file)
 9553 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9559     # check output
 9560     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 9561     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-two-vars-in-memory: error message")
 9562     # check that stop(1) was called
 9563     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 9564     # don't restore from ebp
 9565     81 0/subop/add %esp 8/imm32
 9566     # . epilogue
 9567     5d/pop-to-ebp
 9568     c3/return
 9569 
 9570 test-compare-non-scalar:
 9571     # . prologue
 9572     55/push-ebp
 9573     89/<- %ebp 4/r32/esp
 9574     # setup
 9575     (clear-stream _test-input-stream)
 9576     (clear-stream $_test-input-buffered-file->buffer)
 9577     (clear-stream _test-output-stream)
 9578     (clear-stream $_test-output-buffered-file->buffer)
 9579     (clear-stream _test-error-stream)
 9580     (clear-stream $_test-error-buffered-file->buffer)
 9581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9582     68/push 0/imm32
 9583     68/push 0/imm32
 9584     89/<- %edx 4/r32/esp
 9585     (tailor-exit-descriptor %edx 0x10)
 9586     #
 9587     (write _test-input-stream "fn foo {\n")
 9588     (write _test-input-stream "  var x: (handle int)\n")
 9589     (write _test-input-stream "  var y: int\n")
 9590     (write _test-input-stream "  compare y, x\n")
 9591     (write _test-input-stream "}\n")
 9592     # convert
 9593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9594     # registers except esp clobbered at this point
 9595     # restore ed
 9596     89/<- %edx 4/r32/esp
 9597     (flush _test-output-buffered-file)
 9598     (flush _test-error-buffered-file)
 9599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9605     # check output
 9606     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 9607 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'x' is too large to compare"  "F - test-compare-non-scalar: error message")
 9608     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 9609     # check that stop(1) was called
 9610     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 9611     # don't restore from ebp
 9612     81 0/subop/add %esp 8/imm32
 9613     # . epilogue
 9614     5d/pop-to-ebp
 9615     c3/return
 9616 
 9617 test-compare-with-string-literal:
 9618     # . prologue
 9619     55/push-ebp
 9620     89/<- %ebp 4/r32/esp
 9621     # setup
 9622     (clear-stream _test-input-stream)
 9623     (clear-stream $_test-input-buffered-file->buffer)
 9624     (clear-stream _test-output-stream)
 9625     (clear-stream $_test-output-buffered-file->buffer)
 9626     (clear-stream _test-error-stream)
 9627     (clear-stream $_test-error-buffered-file->buffer)
 9628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9629     68/push 0/imm32
 9630     68/push 0/imm32
 9631     89/<- %edx 4/r32/esp
 9632     (tailor-exit-descriptor %edx 0x10)
 9633     #
 9634     (write _test-input-stream "fn foo {\n")
 9635     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
 9636     (write _test-input-stream "  compare x, \"abc\"\n")
 9637     (write _test-input-stream "}\n")
 9638     # convert
 9639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9640     # registers except esp clobbered at this point
 9641     # restore ed
 9642     89/<- %edx 4/r32/esp
 9643     (flush _test-output-buffered-file)
 9644     (flush _test-error-buffered-file)
 9645 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9651     # check output
 9652     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
 9653     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: string literal \"abc\" is not supported; use the string-equal? function"  "F - test-compare-with-string-literal: error message")
 9654     # check that stop(1) was called
 9655     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
 9656     # don't restore from ebp
 9657     81 0/subop/add %esp 8/imm32
 9658     # . epilogue
 9659     5d/pop-to-ebp
 9660     c3/return
 9661 
 9662 test-address-with-no-inout:
 9663     # . prologue
 9664     55/push-ebp
 9665     89/<- %ebp 4/r32/esp
 9666     # setup
 9667     (clear-stream _test-input-stream)
 9668     (clear-stream $_test-input-buffered-file->buffer)
 9669     (clear-stream _test-output-stream)
 9670     (clear-stream $_test-output-buffered-file->buffer)
 9671     (clear-stream _test-error-stream)
 9672     (clear-stream $_test-error-buffered-file->buffer)
 9673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9674     68/push 0/imm32
 9675     68/push 0/imm32
 9676     89/<- %edx 4/r32/esp
 9677     (tailor-exit-descriptor %edx 0x10)
 9678     #
 9679     (write _test-input-stream "fn foo {\n")
 9680     (write _test-input-stream "  var x/eax: boolean <- address\n")
 9681     (write _test-input-stream "}\n")
 9682     # convert
 9683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9684     # registers except esp clobbered at this point
 9685     # restore ed
 9686     89/<- %edx 4/r32/esp
 9687     (flush _test-output-buffered-file)
 9688     (flush _test-error-buffered-file)
 9689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9695     # check output
 9696     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 9697     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 9698     # check that stop(1) was called
 9699     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 9700     # don't restore from ebp
 9701     81 0/subop/add %esp 8/imm32
 9702     # . epilogue
 9703     5d/pop-to-ebp
 9704     c3/return
 9705 
 9706 test-address-with-multiple-inouts:
 9707     # . prologue
 9708     55/push-ebp
 9709     89/<- %ebp 4/r32/esp
 9710     # setup
 9711     (clear-stream _test-input-stream)
 9712     (clear-stream $_test-input-buffered-file->buffer)
 9713     (clear-stream _test-output-stream)
 9714     (clear-stream $_test-output-buffered-file->buffer)
 9715     (clear-stream _test-error-stream)
 9716     (clear-stream $_test-error-buffered-file->buffer)
 9717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9718     68/push 0/imm32
 9719     68/push 0/imm32
 9720     89/<- %edx 4/r32/esp
 9721     (tailor-exit-descriptor %edx 0x10)
 9722     #
 9723     (write _test-input-stream "fn foo {\n")
 9724     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 9725     (write _test-input-stream "}\n")
 9726     # convert
 9727     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9728     # registers except esp clobbered at this point
 9729     # restore ed
 9730     89/<- %edx 4/r32/esp
 9731     (flush _test-output-buffered-file)
 9732     (flush _test-error-buffered-file)
 9733 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9739     # check output
 9740     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 9741     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one inout"  "F - test-address-with-multiple-inouts: error message")
 9742     # check that stop(1) was called
 9743     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 9744     # don't restore from ebp
 9745     81 0/subop/add %esp 8/imm32
 9746     # . epilogue
 9747     5d/pop-to-ebp
 9748     c3/return
 9749 
 9750 test-address-with-no-output:
 9751     # . prologue
 9752     55/push-ebp
 9753     89/<- %ebp 4/r32/esp
 9754     # setup
 9755     (clear-stream _test-input-stream)
 9756     (clear-stream $_test-input-buffered-file->buffer)
 9757     (clear-stream _test-output-stream)
 9758     (clear-stream $_test-output-buffered-file->buffer)
 9759     (clear-stream _test-error-stream)
 9760     (clear-stream $_test-error-buffered-file->buffer)
 9761     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9762     68/push 0/imm32
 9763     68/push 0/imm32
 9764     89/<- %edx 4/r32/esp
 9765     (tailor-exit-descriptor %edx 0x10)
 9766     #
 9767     (write _test-input-stream "fn foo {\n")
 9768     (write _test-input-stream "  address 0\n")
 9769     (write _test-input-stream "}\n")
 9770     # convert
 9771     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9772     # registers except esp clobbered at this point
 9773     # restore ed
 9774     89/<- %edx 4/r32/esp
 9775     (flush _test-output-buffered-file)
 9776     (flush _test-error-buffered-file)
 9777 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9783     # check output
 9784     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 9785     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 9786     # check that stop(1) was called
 9787     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 9788     # don't restore from ebp
 9789     81 0/subop/add %esp 8/imm32
 9790     # . epilogue
 9791     5d/pop-to-ebp
 9792     c3/return
 9793 
 9794 test-address-with-multiple-outputs:
 9795     # . prologue
 9796     55/push-ebp
 9797     89/<- %ebp 4/r32/esp
 9798     # setup
 9799     (clear-stream _test-input-stream)
 9800     (clear-stream $_test-input-buffered-file->buffer)
 9801     (clear-stream _test-output-stream)
 9802     (clear-stream $_test-output-buffered-file->buffer)
 9803     (clear-stream _test-error-stream)
 9804     (clear-stream $_test-error-buffered-file->buffer)
 9805     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9806     68/push 0/imm32
 9807     68/push 0/imm32
 9808     89/<- %edx 4/r32/esp
 9809     (tailor-exit-descriptor %edx 0x10)
 9810     #
 9811     (write _test-input-stream "fn foo {\n")
 9812     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 9813     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 9814     (write _test-input-stream "  x, y <- address 0\n")
 9815     (write _test-input-stream "}\n")
 9816     # convert
 9817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9818     # registers except esp clobbered at this point
 9819     # restore ed
 9820     89/<- %edx 4/r32/esp
 9821     (flush _test-output-buffered-file)
 9822     (flush _test-error-buffered-file)
 9823 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9829     # check output
 9830     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 9831     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one output"  "F - test-address-with-multiple-outputs: error message")
 9832     # check that stop(1) was called
 9833     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 9834     # don't restore from ebp
 9835     81 0/subop/add %esp 8/imm32
 9836     # . epilogue
 9837     5d/pop-to-ebp
 9838     c3/return
 9839 
 9840 # silly but it works
 9841 test-address-of-deref:
 9842     # . prologue
 9843     55/push-ebp
 9844     89/<- %ebp 4/r32/esp
 9845     # setup
 9846     (clear-stream _test-input-stream)
 9847     (clear-stream $_test-input-buffered-file->buffer)
 9848     (clear-stream _test-output-stream)
 9849     (clear-stream $_test-output-buffered-file->buffer)
 9850     #
 9851     (write _test-input-stream "fn foo {\n")
 9852     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 9853     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 9854     (write _test-input-stream "}\n")
 9855     # convert
 9856     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9857     (flush _test-output-buffered-file)
 9858     # no errors
 9859     # . epilogue
 9860     5d/pop-to-ebp
 9861     c3/return
 9862 
 9863 test-address-to-non-register:
 9864     # . prologue
 9865     55/push-ebp
 9866     89/<- %ebp 4/r32/esp
 9867     # setup
 9868     (clear-stream _test-input-stream)
 9869     (clear-stream $_test-input-buffered-file->buffer)
 9870     (clear-stream _test-output-stream)
 9871     (clear-stream $_test-output-buffered-file->buffer)
 9872     (clear-stream _test-error-stream)
 9873     (clear-stream $_test-error-buffered-file->buffer)
 9874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9875     68/push 0/imm32
 9876     68/push 0/imm32
 9877     89/<- %edx 4/r32/esp
 9878     (tailor-exit-descriptor %edx 0x10)
 9879     #
 9880     (write _test-input-stream "fn foo {\n")
 9881     (write _test-input-stream "  var x: (addr int)\n")
 9882     (write _test-input-stream "  x <- address 0\n")
 9883     (write _test-input-stream "}\n")
 9884     # convert
 9885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9886     # registers except esp clobbered at this point
 9887     # restore ed
 9888     89/<- %edx 4/r32/esp
 9889     (flush _test-output-buffered-file)
 9890     (flush _test-error-buffered-file)
 9891 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9897     # check output
 9898     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 9899     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'x' not in a register"  "F - test-address-to-non-register: error message")
 9900     # check that stop(1) was called
 9901     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 9902     # don't restore from ebp
 9903     81 0/subop/add %esp 8/imm32
 9904     # . epilogue
 9905     5d/pop-to-ebp
 9906     c3/return
 9907 
 9908 test-address-with-wrong-type:
 9909     # . prologue
 9910     55/push-ebp
 9911     89/<- %ebp 4/r32/esp
 9912     # setup
 9913     (clear-stream _test-input-stream)
 9914     (clear-stream $_test-input-buffered-file->buffer)
 9915     (clear-stream _test-output-stream)
 9916     (clear-stream $_test-output-buffered-file->buffer)
 9917     (clear-stream _test-error-stream)
 9918     (clear-stream $_test-error-buffered-file->buffer)
 9919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9920     68/push 0/imm32
 9921     68/push 0/imm32
 9922     89/<- %edx 4/r32/esp
 9923     (tailor-exit-descriptor %edx 0x10)
 9924     #
 9925     (write _test-input-stream "fn foo {\n")
 9926     (write _test-input-stream "  var x: int\n")
 9927     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 9928     (write _test-input-stream "}\n")
 9929     # convert
 9930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9931     # registers except esp clobbered at this point
 9932     # restore ed
 9933     89/<- %edx 4/r32/esp
 9934     (flush _test-output-buffered-file)
 9935     (flush _test-error-buffered-file)
 9936 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 9942     # check output
 9943     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 9944     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'y' cannot hold address of 'x'"  "F - test-address-with-wrong-type: error message")
 9945     # check that stop(1) was called
 9946     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 9947     # don't restore from ebp
 9948     81 0/subop/add %esp 8/imm32
 9949     # . epilogue
 9950     5d/pop-to-ebp
 9951     c3/return
 9952 
 9953 test-address-with-right-type-for-array:
 9954     # . prologue
 9955     55/push-ebp
 9956     89/<- %ebp 4/r32/esp
 9957     # setup
 9958     (clear-stream _test-input-stream)
 9959     (clear-stream $_test-input-buffered-file->buffer)
 9960     (clear-stream _test-output-stream)
 9961     (clear-stream $_test-output-buffered-file->buffer)
 9962     #
 9963     (write _test-input-stream "fn foo {\n")
 9964     (write _test-input-stream "  var x: (array int 3)\n")
 9965     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 9966     (write _test-input-stream "}\n")
 9967     # convert
 9968     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9969     (flush _test-output-buffered-file)
 9970     # no errors
 9971     # . epilogue
 9972     89/<- %esp 5/r32/ebp
 9973     5d/pop-to-ebp
 9974     c3/return
 9975 
 9976 test-address-with-right-type-for-stream:
 9977     # . prologue
 9978     55/push-ebp
 9979     89/<- %ebp 4/r32/esp
 9980     # setup
 9981     (clear-stream _test-input-stream)
 9982     (clear-stream $_test-input-buffered-file->buffer)
 9983     (clear-stream _test-output-stream)
 9984     (clear-stream $_test-output-buffered-file->buffer)
 9985     #
 9986     (write _test-input-stream "fn foo {\n")
 9987     (write _test-input-stream "  var x: (stream int 3)\n")
 9988     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 9989     (write _test-input-stream "}\n")
 9990     # convert
 9991     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9992     (flush _test-output-buffered-file)
 9993     # no errors
 9994     # . epilogue
 9995     89/<- %esp 5/r32/ebp
 9996     5d/pop-to-ebp
 9997     c3/return
 9998 
 9999 test-get-with-wrong-field:
10000     # . prologue
10001     55/push-ebp
10002     89/<- %ebp 4/r32/esp
10003     # setup
10004     (clear-stream _test-input-stream)
10005     (clear-stream $_test-input-buffered-file->buffer)
10006     (clear-stream _test-output-stream)
10007     (clear-stream $_test-output-buffered-file->buffer)
10008     (clear-stream _test-error-stream)
10009     (clear-stream $_test-error-buffered-file->buffer)
10010     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10011     68/push 0/imm32
10012     68/push 0/imm32
10013     89/<- %edx 4/r32/esp
10014     (tailor-exit-descriptor %edx 0x10)
10015     #
10016     (write _test-input-stream "fn foo {\n")
10017     (write _test-input-stream "  var a: t\n")
10018     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10019     (write _test-input-stream "}\n")
10020     (write _test-input-stream "type t {\n")
10021     (write _test-input-stream "  x: int\n")
10022     (write _test-input-stream "}\n")
10023     # convert
10024     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10025     # registers except esp clobbered at this point
10026     # restore ed
10027     89/<- %edx 4/r32/esp
10028     (flush _test-output-buffered-file)
10029     (flush _test-error-buffered-file)
10030 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10036     # check output
10037     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
10038     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: type 't' has no member called 'y'"  "F - test-get-with-wrong-field: error message")
10039     # check that stop(1) was called
10040     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
10041     # don't restore from ebp
10042     81 0/subop/add %esp 8/imm32
10043     # . epilogue
10044     5d/pop-to-ebp
10045     c3/return
10046 
10047 test-get-with-wrong-base-type:
10048     # . prologue
10049     55/push-ebp
10050     89/<- %ebp 4/r32/esp
10051     # setup
10052     (clear-stream _test-input-stream)
10053     (clear-stream $_test-input-buffered-file->buffer)
10054     (clear-stream _test-output-stream)
10055     (clear-stream $_test-output-buffered-file->buffer)
10056     (clear-stream _test-error-stream)
10057     (clear-stream $_test-error-buffered-file->buffer)
10058     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10059     68/push 0/imm32
10060     68/push 0/imm32
10061     89/<- %edx 4/r32/esp
10062     (tailor-exit-descriptor %edx 0x10)
10063     #
10064     (write _test-input-stream "fn foo {\n")
10065     (write _test-input-stream "  var a: int\n")
10066     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10067     (write _test-input-stream "}\n")
10068     # convert
10069     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10070     # registers except esp clobbered at this point
10071     # restore ed
10072     89/<- %edx 4/r32/esp
10073     (flush _test-output-buffered-file)
10074     (flush _test-error-buffered-file)
10075 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10081     # check output
10082     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
10083     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type: error message")
10084     # check that stop(1) was called
10085     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
10086     # don't restore from ebp
10087     81 0/subop/add %esp 8/imm32
10088     # . epilogue
10089     5d/pop-to-ebp
10090     c3/return
10091 
10092 test-get-with-wrong-base-type-2:
10093     # . prologue
10094     55/push-ebp
10095     89/<- %ebp 4/r32/esp
10096     # setup
10097     (clear-stream _test-input-stream)
10098     (clear-stream $_test-input-buffered-file->buffer)
10099     (clear-stream _test-output-stream)
10100     (clear-stream $_test-output-buffered-file->buffer)
10101     (clear-stream _test-error-stream)
10102     (clear-stream $_test-error-buffered-file->buffer)
10103     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10104     68/push 0/imm32
10105     68/push 0/imm32
10106     89/<- %edx 4/r32/esp
10107     (tailor-exit-descriptor %edx 0x10)
10108     #
10109     (write _test-input-stream "fn foo {\n")
10110     (write _test-input-stream "  var a: (addr t)\n")
10111     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10112     (write _test-input-stream "}\n")
10113     (write _test-input-stream "type t {\n")
10114     (write _test-input-stream "  x: int\n")
10115     (write _test-input-stream "}\n")
10116     # convert
10117     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10118     # registers except esp clobbered at this point
10119     # restore ed
10120     89/<- %edx 4/r32/esp
10121     (flush _test-output-buffered-file)
10122     (flush _test-error-buffered-file)
10123 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10129     # check output
10130     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
10131     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' is an 'addr' type, and so must live in a register"  "F - test-get-with-wrong-base-type-2: error message")
10132     # check that stop(1) was called
10133     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
10134     # don't restore from ebp
10135     81 0/subop/add %esp 8/imm32
10136     # . epilogue
10137     5d/pop-to-ebp
10138     c3/return
10139 
10140 test-get-with-wrong-base-type-3:
10141     # . prologue
10142     55/push-ebp
10143     89/<- %ebp 4/r32/esp
10144     # setup
10145     (clear-stream _test-input-stream)
10146     (clear-stream $_test-input-buffered-file->buffer)
10147     (clear-stream _test-output-stream)
10148     (clear-stream $_test-output-buffered-file->buffer)
10149     (clear-stream _test-error-stream)
10150     (clear-stream $_test-error-buffered-file->buffer)
10151     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10152     68/push 0/imm32
10153     68/push 0/imm32
10154     89/<- %edx 4/r32/esp
10155     (tailor-exit-descriptor %edx 0x10)
10156     #
10157     (write _test-input-stream "fn foo {\n")
10158     (write _test-input-stream "  var a: (handle int)\n")
10159     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
10160     (write _test-input-stream "}\n")
10161     # convert
10162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10163     # registers except esp clobbered at this point
10164     # restore ed
10165     89/<- %edx 4/r32/esp
10166     (flush _test-output-buffered-file)
10167     (flush _test-error-buffered-file)
10168 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10174     # check output
10175     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
10176     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type-3: error message")
10177     # check that stop(1) was called
10178     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
10179     # don't restore from ebp
10180     81 0/subop/add %esp 8/imm32
10181     # . epilogue
10182     5d/pop-to-ebp
10183     c3/return
10184 
10185 test-get-with-wrong-offset-type:
10186     # . prologue
10187     55/push-ebp
10188     89/<- %ebp 4/r32/esp
10189     # setup
10190     (clear-stream _test-input-stream)
10191     (clear-stream $_test-input-buffered-file->buffer)
10192     (clear-stream _test-output-stream)
10193     (clear-stream $_test-output-buffered-file->buffer)
10194     (clear-stream _test-error-stream)
10195     (clear-stream $_test-error-buffered-file->buffer)
10196     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10197     68/push 0/imm32
10198     68/push 0/imm32
10199     89/<- %edx 4/r32/esp
10200     (tailor-exit-descriptor %edx 0x10)
10201     #
10202     (write _test-input-stream "fn foo {\n")
10203     (write _test-input-stream "  var a: t\n")
10204     (write _test-input-stream "  var b: int\n")
10205     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
10206     (write _test-input-stream "}\n")
10207     (write _test-input-stream "type t {\n")
10208     (write _test-input-stream "  x: int\n")
10209     (write _test-input-stream "}\n")
10210     # convert
10211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10212     # registers except esp clobbered at this point
10213     # restore ed
10214     89/<- %edx 4/r32/esp
10215     (flush _test-output-buffered-file)
10216     (flush _test-error-buffered-file)
10217 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10223     # check output
10224     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
10225     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: type 't' has no member called 'b'"  "F - test-get-with-wrong-offset-type: error message")
10226     # check that stop(1) was called
10227     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
10228     # don't restore from ebp
10229     81 0/subop/add %esp 8/imm32
10230     # . epilogue
10231     5d/pop-to-ebp
10232     c3/return
10233 
10234 test-get-with-wrong-output-type:
10235     # . prologue
10236     55/push-ebp
10237     89/<- %ebp 4/r32/esp
10238     # setup
10239     (clear-stream _test-input-stream)
10240     (clear-stream $_test-input-buffered-file->buffer)
10241     (clear-stream _test-output-stream)
10242     (clear-stream $_test-output-buffered-file->buffer)
10243     (clear-stream _test-error-stream)
10244     (clear-stream $_test-error-buffered-file->buffer)
10245     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10246     68/push 0/imm32
10247     68/push 0/imm32
10248     89/<- %edx 4/r32/esp
10249     (tailor-exit-descriptor %edx 0x10)
10250     #
10251     (write _test-input-stream "fn foo {\n")
10252     (write _test-input-stream "  var a: t\n")
10253     (write _test-input-stream "  var c: (addr int)\n")
10254     (write _test-input-stream "  c <- get a, x\n")
10255     (write _test-input-stream "}\n")
10256     (write _test-input-stream "type t {\n")
10257     (write _test-input-stream "  x: int\n")
10258     (write _test-input-stream "}\n")
10259     # convert
10260     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10261     # registers except esp clobbered at this point
10262     # restore ed
10263     89/<- %edx 4/r32/esp
10264     (flush _test-output-buffered-file)
10265     (flush _test-error-buffered-file)
10266 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10272     # check output
10273     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
10274     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output 'c' is not in a register"  "F - test-get-with-wrong-output-type: error message")
10275     # check that stop(1) was called
10276     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
10277     # don't restore from ebp
10278     81 0/subop/add %esp 8/imm32
10279     # . epilogue
10280     5d/pop-to-ebp
10281     c3/return
10282 
10283 test-get-with-wrong-output-type-2:
10284     # . prologue
10285     55/push-ebp
10286     89/<- %ebp 4/r32/esp
10287     # setup
10288     (clear-stream _test-input-stream)
10289     (clear-stream $_test-input-buffered-file->buffer)
10290     (clear-stream _test-output-stream)
10291     (clear-stream $_test-output-buffered-file->buffer)
10292     (clear-stream _test-error-stream)
10293     (clear-stream $_test-error-buffered-file->buffer)
10294     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10295     68/push 0/imm32
10296     68/push 0/imm32
10297     89/<- %edx 4/r32/esp
10298     (tailor-exit-descriptor %edx 0x10)
10299     #
10300     (write _test-input-stream "fn foo {\n")
10301     (write _test-input-stream "  var a: t\n")
10302     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
10303     (write _test-input-stream "}\n")
10304     (write _test-input-stream "type t {\n")
10305     (write _test-input-stream "  x: int\n")
10306     (write _test-input-stream "}\n")
10307     # convert
10308     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10309     # registers except esp clobbered at this point
10310     # restore ed
10311     89/<- %edx 4/r32/esp
10312     (flush _test-output-buffered-file)
10313     (flush _test-error-buffered-file)
10314 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10320     # check output
10321     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
10322     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-2: error message")
10323     # check that stop(1) was called
10324     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
10325     # don't restore from ebp
10326     81 0/subop/add %esp 8/imm32
10327     # . epilogue
10328     5d/pop-to-ebp
10329     c3/return
10330 
10331 test-get-with-wrong-output-type-3:
10332     # . prologue
10333     55/push-ebp
10334     89/<- %ebp 4/r32/esp
10335     # setup
10336     (clear-stream _test-input-stream)
10337     (clear-stream $_test-input-buffered-file->buffer)
10338     (clear-stream _test-output-stream)
10339     (clear-stream $_test-output-buffered-file->buffer)
10340     (clear-stream _test-error-stream)
10341     (clear-stream $_test-error-buffered-file->buffer)
10342     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10343     68/push 0/imm32
10344     68/push 0/imm32
10345     89/<- %edx 4/r32/esp
10346     (tailor-exit-descriptor %edx 0x10)
10347     #
10348     (write _test-input-stream "fn foo {\n")
10349     (write _test-input-stream "  var a: t\n")
10350     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
10351     (write _test-input-stream "}\n")
10352     (write _test-input-stream "type t {\n")
10353     (write _test-input-stream "  x: int\n")
10354     (write _test-input-stream "}\n")
10355     # convert
10356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10357     # registers except esp clobbered at this point
10358     # restore ed
10359     89/<- %edx 4/r32/esp
10360     (flush _test-output-buffered-file)
10361     (flush _test-error-buffered-file)
10362 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10368     # check output
10369     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
10370     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-3: error message")
10371     # check that stop(1) was called
10372     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
10373     # don't restore from ebp
10374     81 0/subop/add %esp 8/imm32
10375     # . epilogue
10376     5d/pop-to-ebp
10377     c3/return
10378 
10379 test-get-with-wrong-output-type-4:
10380     # . prologue
10381     55/push-ebp
10382     89/<- %ebp 4/r32/esp
10383     # setup
10384     (clear-stream _test-input-stream)
10385     (clear-stream $_test-input-buffered-file->buffer)
10386     (clear-stream _test-output-stream)
10387     (clear-stream $_test-output-buffered-file->buffer)
10388     (clear-stream _test-error-stream)
10389     (clear-stream $_test-error-buffered-file->buffer)
10390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10391     68/push 0/imm32
10392     68/push 0/imm32
10393     89/<- %edx 4/r32/esp
10394     (tailor-exit-descriptor %edx 0x10)
10395     #
10396     (write _test-input-stream "fn foo {\n")
10397     (write _test-input-stream "  var a: t\n")
10398     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
10399     (write _test-input-stream "}\n")
10400     (write _test-input-stream "type t {\n")
10401     (write _test-input-stream "  x: int\n")
10402     (write _test-input-stream "}\n")
10403     # convert
10404     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10405     # registers except esp clobbered at this point
10406     # restore ed
10407     89/<- %edx 4/r32/esp
10408     (flush _test-output-buffered-file)
10409     (flush _test-error-buffered-file)
10410 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10416     # check output
10417     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
10418     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: wrong output type for member 'x' of type 't'"  "F - test-get-with-wrong-output-type-4: error message")
10419     # check that stop(1) was called
10420     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
10421     # don't restore from ebp
10422     81 0/subop/add %esp 8/imm32
10423     # . epilogue
10424     5d/pop-to-ebp
10425     c3/return
10426 
10427 test-get-with-wrong-output-type-5:
10428     # . prologue
10429     55/push-ebp
10430     89/<- %ebp 4/r32/esp
10431     # setup
10432     (clear-stream _test-input-stream)
10433     (clear-stream $_test-input-buffered-file->buffer)
10434     (clear-stream _test-output-stream)
10435     (clear-stream $_test-output-buffered-file->buffer)
10436     #
10437     (write _test-input-stream "fn foo {\n")
10438     (write _test-input-stream "  var a: t\n")
10439     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
10440     (write _test-input-stream "}\n")
10441     (write _test-input-stream "type t {\n")
10442     (write _test-input-stream "  x: (handle int)\n")
10443     (write _test-input-stream "}\n")
10444     # convert
10445     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10446     (flush _test-output-buffered-file)
10447     # no errors
10448     # . epilogue
10449     89/<- %esp 5/r32/ebp
10450     5d/pop-to-ebp
10451     c3/return
10452 
10453 test-get-with-too-few-inouts:
10454     # . prologue
10455     55/push-ebp
10456     89/<- %ebp 4/r32/esp
10457     # setup
10458     (clear-stream _test-input-stream)
10459     (clear-stream $_test-input-buffered-file->buffer)
10460     (clear-stream _test-output-stream)
10461     (clear-stream $_test-output-buffered-file->buffer)
10462     (clear-stream _test-error-stream)
10463     (clear-stream $_test-error-buffered-file->buffer)
10464     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10465     68/push 0/imm32
10466     68/push 0/imm32
10467     89/<- %edx 4/r32/esp
10468     (tailor-exit-descriptor %edx 0x10)
10469     #
10470     (write _test-input-stream "fn foo {\n")
10471     (write _test-input-stream "  var a: t\n")
10472     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
10473     (write _test-input-stream "}\n")
10474     (write _test-input-stream "type t {\n")
10475     (write _test-input-stream "  x: int\n")
10476     (write _test-input-stream "}\n")
10477     # convert
10478     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10479     # registers except esp clobbered at this point
10480     # restore ed
10481     89/<- %edx 4/r32/esp
10482     (flush _test-output-buffered-file)
10483     (flush _test-error-buffered-file)
10484 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10490     # check output
10491     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
10492     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too few inouts (2 required)"  "F - test-get-with-too-few-inouts: error message")
10493     # check that stop(1) was called
10494     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
10495     # don't restore from ebp
10496     81 0/subop/add %esp 8/imm32
10497     # . epilogue
10498     5d/pop-to-ebp
10499     c3/return
10500 
10501 test-get-with-too-many-inouts:
10502     # . prologue
10503     55/push-ebp
10504     89/<- %ebp 4/r32/esp
10505     # setup
10506     (clear-stream _test-input-stream)
10507     (clear-stream $_test-input-buffered-file->buffer)
10508     (clear-stream _test-output-stream)
10509     (clear-stream $_test-output-buffered-file->buffer)
10510     (clear-stream _test-error-stream)
10511     (clear-stream $_test-error-buffered-file->buffer)
10512     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10513     68/push 0/imm32
10514     68/push 0/imm32
10515     89/<- %edx 4/r32/esp
10516     (tailor-exit-descriptor %edx 0x10)
10517     #
10518     (write _test-input-stream "fn foo {\n")
10519     (write _test-input-stream "  var a: t\n")
10520     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
10521     (write _test-input-stream "}\n")
10522     (write _test-input-stream "type t {\n")
10523     (write _test-input-stream "  x: int\n")
10524     (write _test-input-stream "}\n")
10525     # convert
10526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10527     # registers except esp clobbered at this point
10528     # restore ed
10529     89/<- %edx 4/r32/esp
10530     (flush _test-output-buffered-file)
10531     (flush _test-error-buffered-file)
10532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10538     # check output
10539     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
10540     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too many inouts (2 required)"  "F - test-get-with-too-many-inouts: error message")
10541     # check that stop(1) was called
10542     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
10543     # don't restore from ebp
10544     81 0/subop/add %esp 8/imm32
10545     # . epilogue
10546     5d/pop-to-ebp
10547     c3/return
10548 
10549 test-get-with-no-output:
10550     # . prologue
10551     55/push-ebp
10552     89/<- %ebp 4/r32/esp
10553     # setup
10554     (clear-stream _test-input-stream)
10555     (clear-stream $_test-input-buffered-file->buffer)
10556     (clear-stream _test-output-stream)
10557     (clear-stream $_test-output-buffered-file->buffer)
10558     (clear-stream _test-error-stream)
10559     (clear-stream $_test-error-buffered-file->buffer)
10560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10561     68/push 0/imm32
10562     68/push 0/imm32
10563     89/<- %edx 4/r32/esp
10564     (tailor-exit-descriptor %edx 0x10)
10565     #
10566     (write _test-input-stream "fn foo {\n")
10567     (write _test-input-stream "  var a: t\n")
10568     (write _test-input-stream "  get a, x\n")
10569     (write _test-input-stream "}\n")
10570     (write _test-input-stream "type t {\n")
10571     (write _test-input-stream "  x: int\n")
10572     (write _test-input-stream "}\n")
10573     # convert
10574     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10575     # registers except esp clobbered at this point
10576     # restore ed
10577     89/<- %edx 4/r32/esp
10578     (flush _test-output-buffered-file)
10579     (flush _test-error-buffered-file)
10580 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10586     # check output
10587     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
10588     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
10589     # check that stop(1) was called
10590     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
10591     # don't restore from ebp
10592     81 0/subop/add %esp 8/imm32
10593     # . epilogue
10594     5d/pop-to-ebp
10595     c3/return
10596 
10597 test-get-with-too-many-outputs:
10598     # . prologue
10599     55/push-ebp
10600     89/<- %ebp 4/r32/esp
10601     # setup
10602     (clear-stream _test-input-stream)
10603     (clear-stream $_test-input-buffered-file->buffer)
10604     (clear-stream _test-output-stream)
10605     (clear-stream $_test-output-buffered-file->buffer)
10606     (clear-stream _test-error-stream)
10607     (clear-stream $_test-error-buffered-file->buffer)
10608     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10609     68/push 0/imm32
10610     68/push 0/imm32
10611     89/<- %edx 4/r32/esp
10612     (tailor-exit-descriptor %edx 0x10)
10613     #
10614     (write _test-input-stream "fn foo {\n")
10615     (write _test-input-stream "  var a: t\n")
10616     (write _test-input-stream "  var b: int\n")
10617     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
10618     (write _test-input-stream "  c, b <- get a, x\n")
10619     (write _test-input-stream "}\n")
10620     (write _test-input-stream "type t {\n")
10621     (write _test-input-stream "  x: int\n")
10622     (write _test-input-stream "}\n")
10623     # convert
10624     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10625     # registers except esp clobbered at this point
10626     # restore ed
10627     89/<- %edx 4/r32/esp
10628     (flush _test-output-buffered-file)
10629     (flush _test-error-buffered-file)
10630 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10636     # check output
10637     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
10638     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too many outputs (1 required)"  "F - test-get-with-too-many-outputs: error message")
10639     # check that stop(1) was called
10640     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
10641     # don't restore from ebp
10642     81 0/subop/add %esp 8/imm32
10643     # . epilogue
10644     5d/pop-to-ebp
10645     c3/return
10646 
10647 test-convert-array-of-user-defined-types:
10648     # . prologue
10649     55/push-ebp
10650     89/<- %ebp 4/r32/esp
10651     # setup
10652     (clear-stream _test-input-stream)
10653     (clear-stream $_test-input-buffered-file->buffer)
10654     (clear-stream _test-output-stream)
10655     (clear-stream $_test-output-buffered-file->buffer)
10656     #
10657     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10658     (write _test-input-stream "  x: int\n")
10659     (write _test-input-stream "  y: int\n")
10660     (write _test-input-stream "}\n")
10661     (write _test-input-stream "fn foo {\n")
10662     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10663     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
10664     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
10665     (write _test-input-stream "}\n")
10666     # convert
10667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10668     (flush _test-output-buffered-file)
10669 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10675     # check output
10676     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
10677     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
10678     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
10679     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
10680     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
10681     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
10682     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
10683     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
10684     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
10685     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
10686     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")"  "F - test-convert-array-of-user-defined-types/10")
10687     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-array-of-user-defined-types/12")
10688     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-array-of-user-defined-types/13")
10689     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/14")
10690     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/15")
10691     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/16")
10692     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/17")
10693     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/18")
10694     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/19")
10695     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/20")
10696     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/21")
10697     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/22")
10698     # . epilogue
10699     89/<- %esp 5/r32/ebp
10700     5d/pop-to-ebp
10701     c3/return
10702 
10703 test-convert-length-of-array-of-user-defined-types-to-eax:
10704     # . prologue
10705     55/push-ebp
10706     89/<- %ebp 4/r32/esp
10707     # setup
10708     (clear-stream _test-input-stream)
10709     (clear-stream $_test-input-buffered-file->buffer)
10710     (clear-stream _test-output-stream)
10711     (clear-stream $_test-output-buffered-file->buffer)
10712     #
10713     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10714     (write _test-input-stream "  x: int\n")
10715     (write _test-input-stream "  y: int\n")
10716     (write _test-input-stream "  z: int\n")
10717     (write _test-input-stream "}\n")
10718     (write _test-input-stream "fn foo {\n")
10719     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10720     (write _test-input-stream "  var x/eax: int <- length arr\n")
10721     (write _test-input-stream "}\n")
10722     # convert
10723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10724     (flush _test-output-buffered-file)
10725 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10731     # check output
10732     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
10733     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
10734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
10735     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/3")
10736     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
10737     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
10738     # var arr
10739     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/6")
10740     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/7")
10741     # length instruction
10742     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
10743     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
10744     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/10")
10745     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/11")
10746     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/12")
10747     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/13")
10748     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types-to-eax/14")
10749     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types-to-eax/15")
10750     # reclaim arr
10751     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/16")
10752     #
10753     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
10754     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
10755     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
10756     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/20")
10757     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/21")
10758     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
10759     # . epilogue
10760     89/<- %esp 5/r32/ebp
10761     5d/pop-to-ebp
10762     c3/return
10763 
10764 test-convert-length-of-array-of-user-defined-types-to-ecx:
10765     # . prologue
10766     55/push-ebp
10767     89/<- %ebp 4/r32/esp
10768     # setup
10769     (clear-stream _test-input-stream)
10770     (clear-stream $_test-input-buffered-file->buffer)
10771     (clear-stream _test-output-stream)
10772     (clear-stream $_test-output-buffered-file->buffer)
10773     #
10774     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10775     (write _test-input-stream "  x: int\n")
10776     (write _test-input-stream "  y: int\n")
10777     (write _test-input-stream "  z: int\n")
10778     (write _test-input-stream "}\n")
10779     (write _test-input-stream "fn foo {\n")
10780     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10781     (write _test-input-stream "  var x/ecx: int <- length arr\n")
10782     (write _test-input-stream "}\n")
10783     # convert
10784     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10785     (flush _test-output-buffered-file)
10786 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10792     # check output
10793     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
10794     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
10795     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
10796     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/3")
10797     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
10798     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
10799     # var a
10800     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/6")
10801     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/7")
10802     # var x
10803     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/8")
10804     # length instruction
10805     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
10806     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
10807     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/11")
10808     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/12")
10809     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/13")
10810     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/14")
10811     (check-next-stream-line-equal _test-output-stream "    89/<- %ecx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/15")
10812     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types-to-ecx/16")
10813     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types-to-ecx/17")
10814     # reclaim x
10815     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/18")
10816     # reclaim a
10817     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/19")
10818     #
10819     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
10820     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
10821     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
10822     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/23")
10823     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/24")
10824     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
10825     # . epilogue
10826     89/<- %esp 5/r32/ebp
10827     5d/pop-to-ebp
10828     c3/return
10829 
10830 test-convert-length-of-array-of-user-defined-types-to-edx:
10831     # . prologue
10832     55/push-ebp
10833     89/<- %ebp 4/r32/esp
10834     # setup
10835     (clear-stream _test-input-stream)
10836     (clear-stream $_test-input-buffered-file->buffer)
10837     (clear-stream _test-output-stream)
10838     (clear-stream $_test-output-buffered-file->buffer)
10839     #
10840     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
10841     (write _test-input-stream "  x: int\n")
10842     (write _test-input-stream "  y: int\n")
10843     (write _test-input-stream "  z: int\n")
10844     (write _test-input-stream "}\n")
10845     (write _test-input-stream "fn foo {\n")
10846     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10847     (write _test-input-stream "  var x/edx: int <- length arr\n")
10848     (write _test-input-stream "}\n")
10849     # convert
10850     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10851     (flush _test-output-buffered-file)
10852 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10858     # check output
10859     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
10860     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
10861     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
10862     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/3")
10863     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
10864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
10865     # var a
10866     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/6")
10867     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/7")
10868     # var x
10869     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/8")
10870     # length instruction
10871     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
10872     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
10873     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/11")
10874     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/12")
10875     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/13")
10876     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/14")
10877     (check-next-stream-line-equal _test-output-stream "    89/<- %edx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/15")
10878     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types-to-edx/16")
10879     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types-to-edx/17")
10880     # reclaim x
10881     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/18")
10882     # reclaim a
10883     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/19")
10884     #
10885     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
10886     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
10887     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
10888     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/23")
10889     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/24")
10890     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
10891     # . epilogue
10892     89/<- %esp 5/r32/ebp
10893     5d/pop-to-ebp
10894     c3/return
10895 
10896 test-convert-length-of-array-of-user-defined-types:
10897     # . prologue
10898     55/push-ebp
10899     89/<- %ebp 4/r32/esp
10900     # setup
10901     (clear-stream _test-input-stream)
10902     (clear-stream $_test-input-buffered-file->buffer)
10903     (clear-stream _test-output-stream)
10904     (clear-stream $_test-output-buffered-file->buffer)
10905     #
10906     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
10907     (write _test-input-stream "  x: int\n")
10908     (write _test-input-stream "  y: int\n")
10909     (write _test-input-stream "  z: int\n")
10910     (write _test-input-stream "}\n")
10911     (write _test-input-stream "fn foo {\n")
10912     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
10913     (write _test-input-stream "  var x/ebx: int <- length arr\n")
10914     (write _test-input-stream "}\n")
10915     # convert
10916     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
10917     (flush _test-output-buffered-file)
10918 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
10924     # check output
10925     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
10926     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
10927     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
10928     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
10929     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
10930     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
10931     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
10932     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types/7")
10933     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
10934     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
10935     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
10936     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
10937     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
10938     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types/13")
10939     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types/14")
10940     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types/15")
10941     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
10942     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
10943     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
10944     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
10945     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
10946     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
10947     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
10948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
10949     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
10950     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
10951     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
10952     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
10953     # . epilogue
10954     89/<- %esp 5/r32/ebp
10955     5d/pop-to-ebp
10956     c3/return
10957 
10958 test-index-with-non-array-atom-base-type:
10959     # . prologue
10960     55/push-ebp
10961     89/<- %ebp 4/r32/esp
10962     # setup
10963     (clear-stream _test-input-stream)
10964     (clear-stream $_test-input-buffered-file->buffer)
10965     (clear-stream _test-output-stream)
10966     (clear-stream $_test-output-buffered-file->buffer)
10967     (clear-stream _test-error-stream)
10968     (clear-stream $_test-error-buffered-file->buffer)
10969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10970     68/push 0/imm32
10971     68/push 0/imm32
10972     89/<- %edx 4/r32/esp
10973     (tailor-exit-descriptor %edx 0x10)
10974     #
10975     (write _test-input-stream "fn foo {\n")
10976     (write _test-input-stream "  var a: int\n")
10977     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10978     (write _test-input-stream "}\n")
10979     # convert
10980     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10981     # registers except esp clobbered at this point
10982     # restore ed
10983     89/<- %edx 4/r32/esp
10984     (flush _test-output-buffered-file)
10985     (flush _test-error-buffered-file)
10986 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
10992     # check output
10993     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
10994     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-atom-base-type: error message")
10995     # check that stop(1) was called
10996     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
10997     # don't restore from ebp
10998     81 0/subop/add %esp 8/imm32
10999     # . epilogue
11000     5d/pop-to-ebp
11001     c3/return
11002 
11003 test-index-with-non-array-compound-base-type:
11004     # . prologue
11005     55/push-ebp
11006     89/<- %ebp 4/r32/esp
11007     # setup
11008     (clear-stream _test-input-stream)
11009     (clear-stream $_test-input-buffered-file->buffer)
11010     (clear-stream _test-output-stream)
11011     (clear-stream $_test-output-buffered-file->buffer)
11012     (clear-stream _test-error-stream)
11013     (clear-stream $_test-error-buffered-file->buffer)
11014     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11015     68/push 0/imm32
11016     68/push 0/imm32
11017     89/<- %edx 4/r32/esp
11018     (tailor-exit-descriptor %edx 0x10)
11019     #
11020     (write _test-input-stream "fn foo {\n")
11021     (write _test-input-stream "  var a: (handle int)\n")
11022     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11023     (write _test-input-stream "}\n")
11024     # convert
11025     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11026     # registers except esp clobbered at this point
11027     # restore ed
11028     89/<- %edx 4/r32/esp
11029     (flush _test-output-buffered-file)
11030     (flush _test-error-buffered-file)
11031 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11037     # check output
11038     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
11039     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type: error message")
11040     # check that stop(1) was called
11041     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
11042     # don't restore from ebp
11043     81 0/subop/add %esp 8/imm32
11044     # . epilogue
11045     5d/pop-to-ebp
11046     c3/return
11047 
11048 test-index-with-non-array-compound-base-type-2:
11049     # . prologue
11050     55/push-ebp
11051     89/<- %ebp 4/r32/esp
11052     # setup
11053     (clear-stream _test-input-stream)
11054     (clear-stream $_test-input-buffered-file->buffer)
11055     (clear-stream _test-output-stream)
11056     (clear-stream $_test-output-buffered-file->buffer)
11057     (clear-stream _test-error-stream)
11058     (clear-stream $_test-error-buffered-file->buffer)
11059     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11060     68/push 0/imm32
11061     68/push 0/imm32
11062     89/<- %edx 4/r32/esp
11063     (tailor-exit-descriptor %edx 0x10)
11064     #
11065     (write _test-input-stream "fn foo {\n")
11066     (write _test-input-stream "  var a: (addr int)\n")
11067     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11068     (write _test-input-stream "}\n")
11069     # convert
11070     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11071     # registers except esp clobbered at this point
11072     # restore ed
11073     89/<- %edx 4/r32/esp
11074     (flush _test-output-buffered-file)
11075     (flush _test-error-buffered-file)
11076 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11082     # check output
11083     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
11084     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type-2: error message")
11085     # check that stop(1) was called
11086     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
11087     # don't restore from ebp
11088     81 0/subop/add %esp 8/imm32
11089     # . epilogue
11090     5d/pop-to-ebp
11091     c3/return
11092 
11093 test-index-with-array-atom-base-type:
11094     # . prologue
11095     55/push-ebp
11096     89/<- %ebp 4/r32/esp
11097     # setup
11098     (clear-stream _test-input-stream)
11099     (clear-stream $_test-input-buffered-file->buffer)
11100     (clear-stream _test-output-stream)
11101     (clear-stream $_test-output-buffered-file->buffer)
11102     (clear-stream _test-error-stream)
11103     (clear-stream $_test-error-buffered-file->buffer)
11104     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11105     68/push 0/imm32
11106     68/push 0/imm32
11107     89/<- %edx 4/r32/esp
11108     (tailor-exit-descriptor %edx 0x10)
11109     #
11110     (write _test-input-stream "fn foo {\n")
11111     (write _test-input-stream "  var a: array\n")
11112     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11113     (write _test-input-stream "}\n")
11114     # convert
11115     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11116     # registers except esp clobbered at this point
11117     # restore ed
11118     89/<- %edx 4/r32/esp
11119     (flush _test-output-buffered-file)
11120     (flush _test-error-buffered-file)
11121 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11127     # check output
11128     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
11129     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: array 'a' must specify the type of its elements"  "F - test-index-with-array-atom-base-type: error message")
11130     # check that stop(1) was called
11131     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
11132     # don't restore from ebp
11133     81 0/subop/add %esp 8/imm32
11134     # . epilogue
11135     5d/pop-to-ebp
11136     c3/return
11137 
11138 test-index-with-addr-base-on-stack:
11139     # . prologue
11140     55/push-ebp
11141     89/<- %ebp 4/r32/esp
11142     # setup
11143     (clear-stream _test-input-stream)
11144     (clear-stream $_test-input-buffered-file->buffer)
11145     (clear-stream _test-output-stream)
11146     (clear-stream $_test-output-buffered-file->buffer)
11147     (clear-stream _test-error-stream)
11148     (clear-stream $_test-error-buffered-file->buffer)
11149     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11150     68/push 0/imm32
11151     68/push 0/imm32
11152     89/<- %edx 4/r32/esp
11153     (tailor-exit-descriptor %edx 0x10)
11154     #
11155     (write _test-input-stream "fn foo {\n")
11156     (write _test-input-stream "  var a: (addr array int)\n")
11157     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
11158     (write _test-input-stream "}\n")
11159     # convert
11160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11161     # registers except esp clobbered at this point
11162     # restore ed
11163     89/<- %edx 4/r32/esp
11164     (flush _test-output-buffered-file)
11165     (flush _test-error-buffered-file)
11166 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11172     # check output
11173     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
11174     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is an addr to an array, and so must live in a register"  "F - test-index-with-addr-base-on-stack: error message")
11175     # check that stop(1) was called
11176     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
11177     # don't restore from ebp
11178     81 0/subop/add %esp 8/imm32
11179     # . epilogue
11180     5d/pop-to-ebp
11181     c3/return
11182 
11183 test-index-with-wrong-index-type:
11184     # . prologue
11185     55/push-ebp
11186     89/<- %ebp 4/r32/esp
11187     # setup
11188     (clear-stream _test-input-stream)
11189     (clear-stream $_test-input-buffered-file->buffer)
11190     (clear-stream _test-output-stream)
11191     (clear-stream $_test-output-buffered-file->buffer)
11192     (clear-stream _test-error-stream)
11193     (clear-stream $_test-error-buffered-file->buffer)
11194     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11195     68/push 0/imm32
11196     68/push 0/imm32
11197     89/<- %edx 4/r32/esp
11198     (tailor-exit-descriptor %edx 0x10)
11199     #
11200     (write _test-input-stream "fn foo {\n")
11201     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11202     (write _test-input-stream "  var b: boolean\n")
11203     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11204     (write _test-input-stream "}\n")
11205     # convert
11206     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11207     # registers except esp clobbered at this point
11208     # restore ed
11209     89/<- %edx 4/r32/esp
11210     (flush _test-output-buffered-file)
11211     (flush _test-error-buffered-file)
11212 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11218     # check output
11219     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
11220     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: second argument 'b' must be an int or offset"  "F - test-index-with-wrong-index-type: error message")
11221     # check that stop(1) was called
11222     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
11223     # don't restore from ebp
11224     81 0/subop/add %esp 8/imm32
11225     # . epilogue
11226     5d/pop-to-ebp
11227     c3/return
11228 
11229 test-index-with-offset-atom-index-type:
11230     # . prologue
11231     55/push-ebp
11232     89/<- %ebp 4/r32/esp
11233     # setup
11234     (clear-stream _test-input-stream)
11235     (clear-stream $_test-input-buffered-file->buffer)
11236     (clear-stream _test-output-stream)
11237     (clear-stream $_test-output-buffered-file->buffer)
11238     (clear-stream _test-error-stream)
11239     (clear-stream $_test-error-buffered-file->buffer)
11240     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11241     68/push 0/imm32
11242     68/push 0/imm32
11243     89/<- %edx 4/r32/esp
11244     (tailor-exit-descriptor %edx 0x10)
11245     #
11246     (write _test-input-stream "fn foo {\n")
11247     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11248     (write _test-input-stream "  var b: offset\n")
11249     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11250     (write _test-input-stream "}\n")
11251     # convert
11252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11253     # registers except esp clobbered at this point
11254     # restore ed
11255     89/<- %edx 4/r32/esp
11256     (flush _test-output-buffered-file)
11257     (flush _test-error-buffered-file)
11258 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11264     # check output
11265     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
11266     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: offset 'b' must specify the type of array elements"  "F - test-index-with-offset-atom-index-type: error message")
11267     # check that stop(1) was called
11268     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
11269     # don't restore from ebp
11270     81 0/subop/add %esp 8/imm32
11271     # . epilogue
11272     5d/pop-to-ebp
11273     c3/return
11274 
11275 test-index-with-offset-on-stack:
11276     # . prologue
11277     55/push-ebp
11278     89/<- %ebp 4/r32/esp
11279     # setup
11280     (clear-stream _test-input-stream)
11281     (clear-stream $_test-input-buffered-file->buffer)
11282     (clear-stream _test-output-stream)
11283     (clear-stream $_test-output-buffered-file->buffer)
11284     (clear-stream _test-error-stream)
11285     (clear-stream $_test-error-buffered-file->buffer)
11286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11287     68/push 0/imm32
11288     68/push 0/imm32
11289     89/<- %edx 4/r32/esp
11290     (tailor-exit-descriptor %edx 0x10)
11291     #
11292     (write _test-input-stream "fn foo {\n")
11293     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11294     (write _test-input-stream "  var b: int\n")
11295     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11296     (write _test-input-stream "}\n")
11297     # convert
11298     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11299     # registers except esp clobbered at this point
11300     # restore ed
11301     89/<- %edx 4/r32/esp
11302     (flush _test-output-buffered-file)
11303     (flush _test-error-buffered-file)
11304 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11310     # check output
11311     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
11312     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: second argument 'b' must be in a register"  "F - test-index-with-offset-on-stack: error message")
11313     # check that stop(1) was called
11314     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
11315     # don't restore from ebp
11316     81 0/subop/add %esp 8/imm32
11317     # . epilogue
11318     5d/pop-to-ebp
11319     c3/return
11320 
11321 test-index-needs-offset-type:
11322     # . prologue
11323     55/push-ebp
11324     89/<- %ebp 4/r32/esp
11325     # setup
11326     (clear-stream _test-input-stream)
11327     (clear-stream $_test-input-buffered-file->buffer)
11328     (clear-stream _test-output-stream)
11329     (clear-stream $_test-output-buffered-file->buffer)
11330     (clear-stream _test-error-stream)
11331     (clear-stream $_test-error-buffered-file->buffer)
11332     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11333     68/push 0/imm32
11334     68/push 0/imm32
11335     89/<- %edx 4/r32/esp
11336     (tailor-exit-descriptor %edx 0x10)
11337     #
11338     (write _test-input-stream "fn foo {\n")
11339     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
11340     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
11341     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
11342     (write _test-input-stream "}\n")
11343     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
11344     (write _test-input-stream "  x: int\n")
11345     (write _test-input-stream "  y: int\n")
11346     (write _test-input-stream "  z: int\n")
11347     (write _test-input-stream "}\n")
11348     # convert
11349     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11350     # registers except esp clobbered at this point
11351     # restore ed
11352     89/<- %edx 4/r32/esp
11353     (flush _test-output-buffered-file)
11354     (flush _test-error-buffered-file)
11355 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11361     # check output
11362     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
11363     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: cannot take an int for array 'a'; create an offset instead. See mu.md for details."  "F - test-index-needs-offset-type: error message")
11364     # check that stop(1) was called
11365     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
11366     # don't restore from ebp
11367     81 0/subop/add %esp 8/imm32
11368     # . epilogue
11369     5d/pop-to-ebp
11370     c3/return
11371 
11372 test-index-with-output-not-address:
11373     # . prologue
11374     55/push-ebp
11375     89/<- %ebp 4/r32/esp
11376     # setup
11377     (clear-stream _test-input-stream)
11378     (clear-stream $_test-input-buffered-file->buffer)
11379     (clear-stream _test-output-stream)
11380     (clear-stream $_test-output-buffered-file->buffer)
11381     (clear-stream _test-error-stream)
11382     (clear-stream $_test-error-buffered-file->buffer)
11383     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11384     68/push 0/imm32
11385     68/push 0/imm32
11386     89/<- %edx 4/r32/esp
11387     (tailor-exit-descriptor %edx 0x10)
11388     #
11389     (write _test-input-stream "fn foo {\n")
11390     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11391     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
11392     (write _test-input-stream "}\n")
11393     # convert
11394     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11395     # registers except esp clobbered at this point
11396     # restore ed
11397     89/<- %edx 4/r32/esp
11398     (flush _test-output-buffered-file)
11399     (flush _test-error-buffered-file)
11400 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11406     # check output
11407     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
11408     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address: error message")
11409     # check that stop(1) was called
11410     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
11411     # don't restore from ebp
11412     81 0/subop/add %esp 8/imm32
11413     # . epilogue
11414     5d/pop-to-ebp
11415     c3/return
11416 
11417 test-index-with-output-not-address-2:
11418     # . prologue
11419     55/push-ebp
11420     89/<- %ebp 4/r32/esp
11421     # setup
11422     (clear-stream _test-input-stream)
11423     (clear-stream $_test-input-buffered-file->buffer)
11424     (clear-stream _test-output-stream)
11425     (clear-stream $_test-output-buffered-file->buffer)
11426     (clear-stream _test-error-stream)
11427     (clear-stream $_test-error-buffered-file->buffer)
11428     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11429     68/push 0/imm32
11430     68/push 0/imm32
11431     89/<- %edx 4/r32/esp
11432     (tailor-exit-descriptor %edx 0x10)
11433     #
11434     (write _test-input-stream "fn foo {\n")
11435     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11436     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
11437     (write _test-input-stream "}\n")
11438     # convert
11439     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11440     # registers except esp clobbered at this point
11441     # restore ed
11442     89/<- %edx 4/r32/esp
11443     (flush _test-output-buffered-file)
11444     (flush _test-error-buffered-file)
11445 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11451     # check output
11452     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
11453     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address-2: error message")
11454     # check that stop(1) was called
11455     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
11456     # don't restore from ebp
11457     81 0/subop/add %esp 8/imm32
11458     # . epilogue
11459     5d/pop-to-ebp
11460     c3/return
11461 
11462 test-index-with-wrong-output-type:
11463     # . prologue
11464     55/push-ebp
11465     89/<- %ebp 4/r32/esp
11466     # setup
11467     (clear-stream _test-input-stream)
11468     (clear-stream $_test-input-buffered-file->buffer)
11469     (clear-stream _test-output-stream)
11470     (clear-stream $_test-output-buffered-file->buffer)
11471     (clear-stream _test-error-stream)
11472     (clear-stream $_test-error-buffered-file->buffer)
11473     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11474     68/push 0/imm32
11475     68/push 0/imm32
11476     89/<- %edx 4/r32/esp
11477     (tailor-exit-descriptor %edx 0x10)
11478     #
11479     (write _test-input-stream "fn foo {\n")
11480     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
11481     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
11482     (write _test-input-stream "}\n")
11483     # convert
11484     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11485     # registers except esp clobbered at this point
11486     # restore ed
11487     89/<- %edx 4/r32/esp
11488     (flush _test-output-buffered-file)
11489     (flush _test-error-buffered-file)
11490 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11496     # check output
11497     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
11498     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-type: error message")
11499     # check that stop(1) was called
11500     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
11501     # don't restore from ebp
11502     81 0/subop/add %esp 8/imm32
11503     # . epilogue
11504     5d/pop-to-ebp
11505     c3/return
11506 
11507 test-index-with-wrong-output-compound-type:
11508     # . prologue
11509     55/push-ebp
11510     89/<- %ebp 4/r32/esp
11511     # setup
11512     (clear-stream _test-input-stream)
11513     (clear-stream $_test-input-buffered-file->buffer)
11514     (clear-stream _test-output-stream)
11515     (clear-stream $_test-output-buffered-file->buffer)
11516     (clear-stream _test-error-stream)
11517     (clear-stream $_test-error-buffered-file->buffer)
11518     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11519     68/push 0/imm32
11520     68/push 0/imm32
11521     89/<- %edx 4/r32/esp
11522     (tailor-exit-descriptor %edx 0x10)
11523     #
11524     (write _test-input-stream "fn foo {\n")
11525     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11526     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
11527     (write _test-input-stream "}\n")
11528     # convert
11529     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11530     # registers except esp clobbered at this point
11531     # restore ed
11532     89/<- %edx 4/r32/esp
11533     (flush _test-output-buffered-file)
11534     (flush _test-error-buffered-file)
11535 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11541     # check output
11542     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
11543     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-compound-type: error message")
11544     # check that stop(1) was called
11545     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
11546     # don't restore from ebp
11547     81 0/subop/add %esp 8/imm32
11548     # . epilogue
11549     5d/pop-to-ebp
11550     c3/return
11551 
11552 test-index-with-no-inouts:
11553     # . prologue
11554     55/push-ebp
11555     89/<- %ebp 4/r32/esp
11556     # setup
11557     (clear-stream _test-input-stream)
11558     (clear-stream $_test-input-buffered-file->buffer)
11559     (clear-stream _test-output-stream)
11560     (clear-stream $_test-output-buffered-file->buffer)
11561     (clear-stream _test-error-stream)
11562     (clear-stream $_test-error-buffered-file->buffer)
11563     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11564     68/push 0/imm32
11565     68/push 0/imm32
11566     89/<- %edx 4/r32/esp
11567     (tailor-exit-descriptor %edx 0x10)
11568     #
11569     (write _test-input-stream "fn foo {\n")
11570     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
11571     (write _test-input-stream "}\n")
11572     # convert
11573     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11574     # registers except esp clobbered at this point
11575     # restore ed
11576     89/<- %edx 4/r32/esp
11577     (flush _test-output-buffered-file)
11578     (flush _test-error-buffered-file)
11579 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11585     # check output
11586     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
11587     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-no-inouts: error message")
11588     # check that stop(1) was called
11589     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
11590     # don't restore from ebp
11591     81 0/subop/add %esp 8/imm32
11592     # . epilogue
11593     5d/pop-to-ebp
11594     c3/return
11595 
11596 test-index-with-too-few-inouts:
11597     # . prologue
11598     55/push-ebp
11599     89/<- %ebp 4/r32/esp
11600     # setup
11601     (clear-stream _test-input-stream)
11602     (clear-stream $_test-input-buffered-file->buffer)
11603     (clear-stream _test-output-stream)
11604     (clear-stream $_test-output-buffered-file->buffer)
11605     (clear-stream _test-error-stream)
11606     (clear-stream $_test-error-buffered-file->buffer)
11607     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11608     68/push 0/imm32
11609     68/push 0/imm32
11610     89/<- %edx 4/r32/esp
11611     (tailor-exit-descriptor %edx 0x10)
11612     #
11613     (write _test-input-stream "fn foo {\n")
11614     (write _test-input-stream "  var a: (array int 3)\n")
11615     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
11616     (write _test-input-stream "}\n")
11617     # convert
11618     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11619     # registers except esp clobbered at this point
11620     # restore ed
11621     89/<- %edx 4/r32/esp
11622     (flush _test-output-buffered-file)
11623     (flush _test-error-buffered-file)
11624 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11630     # check output
11631     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
11632     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-too-few-inouts: error message")
11633     # check that stop(1) was called
11634     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
11635     # don't restore from ebp
11636     81 0/subop/add %esp 8/imm32
11637     # . epilogue
11638     5d/pop-to-ebp
11639     c3/return
11640 
11641 test-index-with-too-many-inouts:
11642     # . prologue
11643     55/push-ebp
11644     89/<- %ebp 4/r32/esp
11645     # setup
11646     (clear-stream _test-input-stream)
11647     (clear-stream $_test-input-buffered-file->buffer)
11648     (clear-stream _test-output-stream)
11649     (clear-stream $_test-output-buffered-file->buffer)
11650     (clear-stream _test-error-stream)
11651     (clear-stream $_test-error-buffered-file->buffer)
11652     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11653     68/push 0/imm32
11654     68/push 0/imm32
11655     89/<- %edx 4/r32/esp
11656     (tailor-exit-descriptor %edx 0x10)
11657     #
11658     (write _test-input-stream "fn foo {\n")
11659     (write _test-input-stream "  var a: (array int 3)\n")
11660     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
11661     (write _test-input-stream "}\n")
11662     # convert
11663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11664     # registers except esp clobbered at this point
11665     # restore ed
11666     89/<- %edx 4/r32/esp
11667     (flush _test-output-buffered-file)
11668     (flush _test-error-buffered-file)
11669 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11675     # check output
11676     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
11677     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too many inouts (2 required)"  "F - test-index-with-too-many-inouts: error message")
11678     # check that stop(1) was called
11679     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
11680     # don't restore from ebp
11681     81 0/subop/add %esp 8/imm32
11682     # . epilogue
11683     5d/pop-to-ebp
11684     c3/return
11685 
11686 test-index-with-no-output:
11687     # . prologue
11688     55/push-ebp
11689     89/<- %ebp 4/r32/esp
11690     # setup
11691     (clear-stream _test-input-stream)
11692     (clear-stream $_test-input-buffered-file->buffer)
11693     (clear-stream _test-output-stream)
11694     (clear-stream $_test-output-buffered-file->buffer)
11695     (clear-stream _test-error-stream)
11696     (clear-stream $_test-error-buffered-file->buffer)
11697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11698     68/push 0/imm32
11699     68/push 0/imm32
11700     89/<- %edx 4/r32/esp
11701     (tailor-exit-descriptor %edx 0x10)
11702     #
11703     (write _test-input-stream "fn foo {\n")
11704     (write _test-input-stream "  var a: (array int 3)\n")
11705     (write _test-input-stream "  index a, 0\n")
11706     (write _test-input-stream "}\n")
11707     # convert
11708     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11709     # registers except esp clobbered at this point
11710     # restore ed
11711     89/<- %edx 4/r32/esp
11712     (flush _test-output-buffered-file)
11713     (flush _test-error-buffered-file)
11714 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11720     # check output
11721     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
11722     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
11723     # check that stop(1) was called
11724     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
11725     # don't restore from ebp
11726     81 0/subop/add %esp 8/imm32
11727     # . epilogue
11728     5d/pop-to-ebp
11729     c3/return
11730 
11731 test-index-with-too-many-outputs:
11732     # . prologue
11733     55/push-ebp
11734     89/<- %ebp 4/r32/esp
11735     # setup
11736     (clear-stream _test-input-stream)
11737     (clear-stream $_test-input-buffered-file->buffer)
11738     (clear-stream _test-output-stream)
11739     (clear-stream $_test-output-buffered-file->buffer)
11740     (clear-stream _test-error-stream)
11741     (clear-stream $_test-error-buffered-file->buffer)
11742     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11743     68/push 0/imm32
11744     68/push 0/imm32
11745     89/<- %edx 4/r32/esp
11746     (tailor-exit-descriptor %edx 0x10)
11747     #
11748     (write _test-input-stream "fn foo {\n")
11749     (write _test-input-stream "  var a: (array int 3)\n")
11750     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11751     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11752     (write _test-input-stream "  b, c <- index a, 0\n")
11753     (write _test-input-stream "}\n")
11754     # convert
11755     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11756     # registers except esp clobbered at this point
11757     # restore ed
11758     89/<- %edx 4/r32/esp
11759     (flush _test-output-buffered-file)
11760     (flush _test-error-buffered-file)
11761 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11767     # check output
11768     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
11769     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too many outputs (1 required)"  "F - test-index-with-too-many-outputs: error message")
11770     # check that stop(1) was called
11771     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
11772     # don't restore from ebp
11773     81 0/subop/add %esp 8/imm32
11774     # . epilogue
11775     5d/pop-to-ebp
11776     c3/return
11777 
11778 test-compute-offset-with-non-array-atom-base-type:
11779     # . prologue
11780     55/push-ebp
11781     89/<- %ebp 4/r32/esp
11782     # setup
11783     (clear-stream _test-input-stream)
11784     (clear-stream $_test-input-buffered-file->buffer)
11785     (clear-stream _test-output-stream)
11786     (clear-stream $_test-output-buffered-file->buffer)
11787     (clear-stream _test-error-stream)
11788     (clear-stream $_test-error-buffered-file->buffer)
11789     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11790     68/push 0/imm32
11791     68/push 0/imm32
11792     89/<- %edx 4/r32/esp
11793     (tailor-exit-descriptor %edx 0x10)
11794     #
11795     (write _test-input-stream "fn foo {\n")
11796     (write _test-input-stream "  var a: int\n")
11797     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11798     (write _test-input-stream "}\n")
11799     # convert
11800     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11801     # registers except esp clobbered at this point
11802     # restore ed
11803     89/<- %edx 4/r32/esp
11804     (flush _test-output-buffered-file)
11805     (flush _test-error-buffered-file)
11806 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11812     # check output
11813     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
11814     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-atom-base-type: error message")
11815     # check that stop(1) was called
11816     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
11817     # don't restore from ebp
11818     81 0/subop/add %esp 8/imm32
11819     # . epilogue
11820     5d/pop-to-ebp
11821     c3/return
11822 
11823 test-compute-offset-with-non-array-compound-base-type:
11824     # . prologue
11825     55/push-ebp
11826     89/<- %ebp 4/r32/esp
11827     # setup
11828     (clear-stream _test-input-stream)
11829     (clear-stream $_test-input-buffered-file->buffer)
11830     (clear-stream _test-output-stream)
11831     (clear-stream $_test-output-buffered-file->buffer)
11832     (clear-stream _test-error-stream)
11833     (clear-stream $_test-error-buffered-file->buffer)
11834     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11835     68/push 0/imm32
11836     68/push 0/imm32
11837     89/<- %edx 4/r32/esp
11838     (tailor-exit-descriptor %edx 0x10)
11839     #
11840     (write _test-input-stream "fn foo {\n")
11841     (write _test-input-stream "  var a: (handle int)\n")
11842     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11843     (write _test-input-stream "}\n")
11844     # convert
11845     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11846     # registers except esp clobbered at this point
11847     # restore ed
11848     89/<- %edx 4/r32/esp
11849     (flush _test-output-buffered-file)
11850     (flush _test-error-buffered-file)
11851 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11857     # check output
11858     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
11859     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type: error message")
11860     # check that stop(1) was called
11861     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
11862     # don't restore from ebp
11863     81 0/subop/add %esp 8/imm32
11864     # . epilogue
11865     5d/pop-to-ebp
11866     c3/return
11867 
11868 test-compute-offset-with-non-array-compound-base-type-2:
11869     # . prologue
11870     55/push-ebp
11871     89/<- %ebp 4/r32/esp
11872     # setup
11873     (clear-stream _test-input-stream)
11874     (clear-stream $_test-input-buffered-file->buffer)
11875     (clear-stream _test-output-stream)
11876     (clear-stream $_test-output-buffered-file->buffer)
11877     (clear-stream _test-error-stream)
11878     (clear-stream $_test-error-buffered-file->buffer)
11879     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11880     68/push 0/imm32
11881     68/push 0/imm32
11882     89/<- %edx 4/r32/esp
11883     (tailor-exit-descriptor %edx 0x10)
11884     #
11885     (write _test-input-stream "fn foo {\n")
11886     (write _test-input-stream "  var a: (addr int)\n")
11887     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11888     (write _test-input-stream "}\n")
11889     # convert
11890     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11891     # registers except esp clobbered at this point
11892     # restore ed
11893     89/<- %edx 4/r32/esp
11894     (flush _test-output-buffered-file)
11895     (flush _test-error-buffered-file)
11896 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11902     # check output
11903     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
11904     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type-2: error message")
11905     # check that stop(1) was called
11906     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
11907     # don't restore from ebp
11908     81 0/subop/add %esp 8/imm32
11909     # . epilogue
11910     5d/pop-to-ebp
11911     c3/return
11912 
11913 test-compute-offset-with-array-atom-base-type:
11914     # . prologue
11915     55/push-ebp
11916     89/<- %ebp 4/r32/esp
11917     # setup
11918     (clear-stream _test-input-stream)
11919     (clear-stream $_test-input-buffered-file->buffer)
11920     (clear-stream _test-output-stream)
11921     (clear-stream $_test-output-buffered-file->buffer)
11922     (clear-stream _test-error-stream)
11923     (clear-stream $_test-error-buffered-file->buffer)
11924     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11925     68/push 0/imm32
11926     68/push 0/imm32
11927     89/<- %edx 4/r32/esp
11928     (tailor-exit-descriptor %edx 0x10)
11929     #
11930     (write _test-input-stream "fn foo {\n")
11931     (write _test-input-stream "  var a: array\n")
11932     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
11933     (write _test-input-stream "}\n")
11934     # convert
11935     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11936     # registers except esp clobbered at this point
11937     # restore ed
11938     89/<- %edx 4/r32/esp
11939     (flush _test-output-buffered-file)
11940     (flush _test-error-buffered-file)
11941 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11947     # check output
11948     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
11949     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: array 'a' must specify the type of its elements"  "F - test-compute-offset-with-array-atom-base-type: error message")
11950     # check that stop(1) was called
11951     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
11952     # don't restore from ebp
11953     81 0/subop/add %esp 8/imm32
11954     # . epilogue
11955     5d/pop-to-ebp
11956     c3/return
11957 
11958 test-compute-offset-with-wrong-index-type:
11959     # . prologue
11960     55/push-ebp
11961     89/<- %ebp 4/r32/esp
11962     # setup
11963     (clear-stream _test-input-stream)
11964     (clear-stream $_test-input-buffered-file->buffer)
11965     (clear-stream _test-output-stream)
11966     (clear-stream $_test-output-buffered-file->buffer)
11967     (clear-stream _test-error-stream)
11968     (clear-stream $_test-error-buffered-file->buffer)
11969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11970     68/push 0/imm32
11971     68/push 0/imm32
11972     89/<- %edx 4/r32/esp
11973     (tailor-exit-descriptor %edx 0x10)
11974     #
11975     (write _test-input-stream "fn foo {\n")
11976     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
11977     (write _test-input-stream "  var b: boolean\n")
11978     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
11979     (write _test-input-stream "}\n")
11980     # convert
11981     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11982     # registers except esp clobbered at this point
11983     # restore ed
11984     89/<- %edx 4/r32/esp
11985     (flush _test-output-buffered-file)
11986     (flush _test-error-buffered-file)
11987 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
11993     # check output
11994     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
11995     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: second argument 'b' must be an int"  "F - test-compute-offset-with-wrong-index-type: error message")
11996     # check that stop(1) was called
11997     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
11998     # don't restore from ebp
11999     81 0/subop/add %esp 8/imm32
12000     # . epilogue
12001     5d/pop-to-ebp
12002     c3/return
12003 
12004 test-compute-offset-with-output-not-offset:
12005     # . prologue
12006     55/push-ebp
12007     89/<- %ebp 4/r32/esp
12008     # setup
12009     (clear-stream _test-input-stream)
12010     (clear-stream $_test-input-buffered-file->buffer)
12011     (clear-stream _test-output-stream)
12012     (clear-stream $_test-output-buffered-file->buffer)
12013     (clear-stream _test-error-stream)
12014     (clear-stream $_test-error-buffered-file->buffer)
12015     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12016     68/push 0/imm32
12017     68/push 0/imm32
12018     89/<- %edx 4/r32/esp
12019     (tailor-exit-descriptor %edx 0x10)
12020     #
12021     (write _test-input-stream "fn foo {\n")
12022     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12023     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
12024     (write _test-input-stream "}\n")
12025     # convert
12026     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12027     # registers except esp clobbered at this point
12028     # restore ed
12029     89/<- %edx 4/r32/esp
12030     (flush _test-output-buffered-file)
12031     (flush _test-error-buffered-file)
12032 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12038     # check output
12039     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
12040     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-offset: error message")
12041     # check that stop(1) was called
12042     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
12043     # don't restore from ebp
12044     81 0/subop/add %esp 8/imm32
12045     # . epilogue
12046     5d/pop-to-ebp
12047     c3/return
12048 
12049 test-compute-offset-with-output-not-address-2:
12050     # . prologue
12051     55/push-ebp
12052     89/<- %ebp 4/r32/esp
12053     # setup
12054     (clear-stream _test-input-stream)
12055     (clear-stream $_test-input-buffered-file->buffer)
12056     (clear-stream _test-output-stream)
12057     (clear-stream $_test-output-buffered-file->buffer)
12058     (clear-stream _test-error-stream)
12059     (clear-stream $_test-error-buffered-file->buffer)
12060     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12061     68/push 0/imm32
12062     68/push 0/imm32
12063     89/<- %edx 4/r32/esp
12064     (tailor-exit-descriptor %edx 0x10)
12065     #
12066     (write _test-input-stream "fn foo {\n")
12067     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12068     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
12069     (write _test-input-stream "}\n")
12070     # convert
12071     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12072     # registers except esp clobbered at this point
12073     # restore ed
12074     89/<- %edx 4/r32/esp
12075     (flush _test-output-buffered-file)
12076     (flush _test-error-buffered-file)
12077 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12083     # check output
12084     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
12085     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-address-2: error message")
12086     # check that stop(1) was called
12087     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
12088     # don't restore from ebp
12089     81 0/subop/add %esp 8/imm32
12090     # . epilogue
12091     5d/pop-to-ebp
12092     c3/return
12093 
12094 test-compute-offset-with-wrong-output-type:
12095     # . prologue
12096     55/push-ebp
12097     89/<- %ebp 4/r32/esp
12098     # setup
12099     (clear-stream _test-input-stream)
12100     (clear-stream $_test-input-buffered-file->buffer)
12101     (clear-stream _test-output-stream)
12102     (clear-stream $_test-output-buffered-file->buffer)
12103     (clear-stream _test-error-stream)
12104     (clear-stream $_test-error-buffered-file->buffer)
12105     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12106     68/push 0/imm32
12107     68/push 0/imm32
12108     89/<- %edx 4/r32/esp
12109     (tailor-exit-descriptor %edx 0x10)
12110     #
12111     (write _test-input-stream "fn foo {\n")
12112     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12113     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
12114     (write _test-input-stream "}\n")
12115     # convert
12116     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12117     # registers except esp clobbered at this point
12118     # restore ed
12119     89/<- %edx 4/r32/esp
12120     (flush _test-output-buffered-file)
12121     (flush _test-error-buffered-file)
12122 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12128     # check output
12129     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
12130     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-type: error message")
12131     # check that stop(1) was called
12132     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
12133     # don't restore from ebp
12134     81 0/subop/add %esp 8/imm32
12135     # . epilogue
12136     5d/pop-to-ebp
12137     c3/return
12138 
12139 test-compute-offset-with-wrong-output-compound-type:
12140     # . prologue
12141     55/push-ebp
12142     89/<- %ebp 4/r32/esp
12143     # setup
12144     (clear-stream _test-input-stream)
12145     (clear-stream $_test-input-buffered-file->buffer)
12146     (clear-stream _test-output-stream)
12147     (clear-stream $_test-output-buffered-file->buffer)
12148     (clear-stream _test-error-stream)
12149     (clear-stream $_test-error-buffered-file->buffer)
12150     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12151     68/push 0/imm32
12152     68/push 0/imm32
12153     89/<- %edx 4/r32/esp
12154     (tailor-exit-descriptor %edx 0x10)
12155     #
12156     (write _test-input-stream "fn foo {\n")
12157     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12158     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
12159     (write _test-input-stream "}\n")
12160     # convert
12161     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12162     # registers except esp clobbered at this point
12163     # restore ed
12164     89/<- %edx 4/r32/esp
12165     (flush _test-output-buffered-file)
12166     (flush _test-error-buffered-file)
12167 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12173     # check output
12174     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
12175     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-compound-type: error message")
12176     # check that stop(1) was called
12177     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
12178     # don't restore from ebp
12179     81 0/subop/add %esp 8/imm32
12180     # . epilogue
12181     5d/pop-to-ebp
12182     c3/return
12183 
12184 test-compute-offset-with-no-inouts:
12185     # . prologue
12186     55/push-ebp
12187     89/<- %ebp 4/r32/esp
12188     # setup
12189     (clear-stream _test-input-stream)
12190     (clear-stream $_test-input-buffered-file->buffer)
12191     (clear-stream _test-output-stream)
12192     (clear-stream $_test-output-buffered-file->buffer)
12193     (clear-stream _test-error-stream)
12194     (clear-stream $_test-error-buffered-file->buffer)
12195     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12196     68/push 0/imm32
12197     68/push 0/imm32
12198     89/<- %edx 4/r32/esp
12199     (tailor-exit-descriptor %edx 0x10)
12200     #
12201     (write _test-input-stream "fn foo {\n")
12202     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
12203     (write _test-input-stream "}\n")
12204     # convert
12205     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12206     # registers except esp clobbered at this point
12207     # restore ed
12208     89/<- %edx 4/r32/esp
12209     (flush _test-output-buffered-file)
12210     (flush _test-error-buffered-file)
12211 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12217     # check output
12218     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
12219     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-no-inouts: error message")
12220     # check that stop(1) was called
12221     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
12222     # don't restore from ebp
12223     81 0/subop/add %esp 8/imm32
12224     # . epilogue
12225     5d/pop-to-ebp
12226     c3/return
12227 
12228 test-compute-offset-with-too-few-inouts:
12229     # . prologue
12230     55/push-ebp
12231     89/<- %ebp 4/r32/esp
12232     # setup
12233     (clear-stream _test-input-stream)
12234     (clear-stream $_test-input-buffered-file->buffer)
12235     (clear-stream _test-output-stream)
12236     (clear-stream $_test-output-buffered-file->buffer)
12237     (clear-stream _test-error-stream)
12238     (clear-stream $_test-error-buffered-file->buffer)
12239     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12240     68/push 0/imm32
12241     68/push 0/imm32
12242     89/<- %edx 4/r32/esp
12243     (tailor-exit-descriptor %edx 0x10)
12244     #
12245     (write _test-input-stream "fn foo {\n")
12246     (write _test-input-stream "  var a: (array int 3)\n")
12247     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
12248     (write _test-input-stream "}\n")
12249     # convert
12250     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12251     # registers except esp clobbered at this point
12252     # restore ed
12253     89/<- %edx 4/r32/esp
12254     (flush _test-output-buffered-file)
12255     (flush _test-error-buffered-file)
12256 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12262     # check output
12263     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
12264     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-too-few-inouts: error message")
12265     # check that stop(1) was called
12266     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
12267     # don't restore from ebp
12268     81 0/subop/add %esp 8/imm32
12269     # . epilogue
12270     5d/pop-to-ebp
12271     c3/return
12272 
12273 test-compute-offset-with-too-many-inouts:
12274     # . prologue
12275     55/push-ebp
12276     89/<- %ebp 4/r32/esp
12277     # setup
12278     (clear-stream _test-input-stream)
12279     (clear-stream $_test-input-buffered-file->buffer)
12280     (clear-stream _test-output-stream)
12281     (clear-stream $_test-output-buffered-file->buffer)
12282     (clear-stream _test-error-stream)
12283     (clear-stream $_test-error-buffered-file->buffer)
12284     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12285     68/push 0/imm32
12286     68/push 0/imm32
12287     89/<- %edx 4/r32/esp
12288     (tailor-exit-descriptor %edx 0x10)
12289     #
12290     (write _test-input-stream "fn foo {\n")
12291     (write _test-input-stream "  var a: (array int 3)\n")
12292     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
12293     (write _test-input-stream "}\n")
12294     # convert
12295     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12296     # registers except esp clobbered at this point
12297     # restore ed
12298     89/<- %edx 4/r32/esp
12299     (flush _test-output-buffered-file)
12300     (flush _test-error-buffered-file)
12301 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12307     # check output
12308     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
12309     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many inouts (2 required)"  "F - test-compute-offset-with-too-many-inouts: error message")
12310     # check that stop(1) was called
12311     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
12312     # don't restore from ebp
12313     81 0/subop/add %esp 8/imm32
12314     # . epilogue
12315     5d/pop-to-ebp
12316     c3/return
12317 
12318 test-compute-offset-with-no-output:
12319     # . prologue
12320     55/push-ebp
12321     89/<- %ebp 4/r32/esp
12322     # setup
12323     (clear-stream _test-input-stream)
12324     (clear-stream $_test-input-buffered-file->buffer)
12325     (clear-stream _test-output-stream)
12326     (clear-stream $_test-output-buffered-file->buffer)
12327     (clear-stream _test-error-stream)
12328     (clear-stream $_test-error-buffered-file->buffer)
12329     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12330     68/push 0/imm32
12331     68/push 0/imm32
12332     89/<- %edx 4/r32/esp
12333     (tailor-exit-descriptor %edx 0x10)
12334     #
12335     (write _test-input-stream "fn foo {\n")
12336     (write _test-input-stream "  var a: (array int 3)\n")
12337     (write _test-input-stream "  compute-offset a, 0\n")
12338     (write _test-input-stream "}\n")
12339     # convert
12340     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12341     # registers except esp clobbered at this point
12342     # restore ed
12343     89/<- %edx 4/r32/esp
12344     (flush _test-output-buffered-file)
12345     (flush _test-error-buffered-file)
12346 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12352     # check output
12353     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
12354     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: must have an output"  "F - test-compute-offset-with-no-output: error message")
12355     # check that stop(1) was called
12356     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
12357     # don't restore from ebp
12358     81 0/subop/add %esp 8/imm32
12359     # . epilogue
12360     5d/pop-to-ebp
12361     c3/return
12362 
12363 test-compute-offset-with-too-many-outputs:
12364     # . prologue
12365     55/push-ebp
12366     89/<- %ebp 4/r32/esp
12367     # setup
12368     (clear-stream _test-input-stream)
12369     (clear-stream $_test-input-buffered-file->buffer)
12370     (clear-stream _test-output-stream)
12371     (clear-stream $_test-output-buffered-file->buffer)
12372     (clear-stream _test-error-stream)
12373     (clear-stream $_test-error-buffered-file->buffer)
12374     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12375     68/push 0/imm32
12376     68/push 0/imm32
12377     89/<- %edx 4/r32/esp
12378     (tailor-exit-descriptor %edx 0x10)
12379     #
12380     (write _test-input-stream "fn foo {\n")
12381     (write _test-input-stream "  var a: (array int 3)\n")
12382     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
12383     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
12384     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
12385     (write _test-input-stream "}\n")
12386     # convert
12387     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12388     # registers except esp clobbered at this point
12389     # restore ed
12390     89/<- %edx 4/r32/esp
12391     (flush _test-output-buffered-file)
12392     (flush _test-error-buffered-file)
12393 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12399     # check output
12400     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
12401     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many outputs (1 required)"  "F - test-compute-offset-with-too-many-outputs: error message")
12402     # check that stop(1) was called
12403     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
12404     # don't restore from ebp
12405     81 0/subop/add %esp 8/imm32
12406     # . epilogue
12407     5d/pop-to-ebp
12408     c3/return
12409 
12410 test-convert-read-from-stream:
12411     # . prologue
12412     55/push-ebp
12413     89/<- %ebp 4/r32/esp
12414     # setup
12415     (clear-stream _test-input-stream)
12416     (clear-stream $_test-input-buffered-file->buffer)
12417     (clear-stream _test-output-stream)
12418     (clear-stream $_test-output-buffered-file->buffer)
12419     #
12420     (write _test-input-stream "fn foo {\n")
12421     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12422     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12423     (write _test-input-stream "  read-from-stream s, o\n")
12424     (write _test-input-stream "}\n")
12425     # convert
12426     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12427     # registers except esp clobbered at this point
12428     # restore ed
12429     89/<- %edx 4/r32/esp
12430     (flush _test-output-buffered-file)
12431     (flush _test-error-buffered-file)
12432 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12438     # check output
12439     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
12440     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
12441     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
12442     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
12443     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
12444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
12445     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
12446     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
12447     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
12448     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
12449     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
12450     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
12451     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
12452     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
12453     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
12454     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
12455     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
12456     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
12457     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
12458     # . epilogue
12459     89/<- %esp 5/r32/ebp
12460     5d/pop-to-ebp
12461     c3/return
12462 
12463 test-convert-read-from-stream-with-correct-payload-size:
12464     # . prologue
12465     55/push-ebp
12466     89/<- %ebp 4/r32/esp
12467     # setup
12468     (clear-stream _test-input-stream)
12469     (clear-stream $_test-input-buffered-file->buffer)
12470     (clear-stream _test-output-stream)
12471     (clear-stream $_test-output-buffered-file->buffer)
12472     #
12473     (write _test-input-stream "fn foo {\n")
12474     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12475     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12476     (write _test-input-stream "  read-from-stream s, o\n")
12477     (write _test-input-stream "}\n")
12478     # convert
12479     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12480     # registers except esp clobbered at this point
12481     # restore ed
12482     89/<- %edx 4/r32/esp
12483     (flush _test-output-buffered-file)
12484     (flush _test-error-buffered-file)
12485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12491     # check output
12492     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
12493     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
12494     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
12495     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
12496     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
12497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
12498     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
12499     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/7")
12500     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
12501     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/9")
12502     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000008)"  "F - test-convert-read-from-stream-with-correct-payload-size/10")
12503     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
12504     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
12505     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
12506     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
12507     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
12508     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
12509     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
12510     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
12511     # . epilogue
12512     89/<- %esp 5/r32/ebp
12513     5d/pop-to-ebp
12514     c3/return
12515 
12516 test-read-from-stream-with-non-stream-atom-base-type:
12517     # . prologue
12518     55/push-ebp
12519     89/<- %ebp 4/r32/esp
12520     # setup
12521     (clear-stream _test-input-stream)
12522     (clear-stream $_test-input-buffered-file->buffer)
12523     (clear-stream _test-output-stream)
12524     (clear-stream $_test-output-buffered-file->buffer)
12525     (clear-stream _test-error-stream)
12526     (clear-stream $_test-error-buffered-file->buffer)
12527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12528     68/push 0/imm32
12529     68/push 0/imm32
12530     89/<- %edx 4/r32/esp
12531     (tailor-exit-descriptor %edx 0x10)
12532     #
12533     (write _test-input-stream "fn foo {\n")
12534     (write _test-input-stream "  var a: int\n")
12535     (write _test-input-stream "  read-from-stream a, 0\n")
12536     (write _test-input-stream "}\n")
12537     # convert
12538     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12539     # registers except esp clobbered at this point
12540     # restore ed
12541     89/<- %edx 4/r32/esp
12542     (flush _test-output-buffered-file)
12543     (flush _test-error-buffered-file)
12544 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12550     # check output
12551     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
12552     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-atom-base-type: error message")
12553     # check that stop(1) was called
12554     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
12555     # don't restore from ebp
12556     81 0/subop/add %esp 8/imm32
12557     # . epilogue
12558     5d/pop-to-ebp
12559     c3/return
12560 
12561 test-read-from-stream-with-non-stream-compound-base-type:
12562     # . prologue
12563     55/push-ebp
12564     89/<- %ebp 4/r32/esp
12565     # setup
12566     (clear-stream _test-input-stream)
12567     (clear-stream $_test-input-buffered-file->buffer)
12568     (clear-stream _test-output-stream)
12569     (clear-stream $_test-output-buffered-file->buffer)
12570     (clear-stream _test-error-stream)
12571     (clear-stream $_test-error-buffered-file->buffer)
12572     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12573     68/push 0/imm32
12574     68/push 0/imm32
12575     89/<- %edx 4/r32/esp
12576     (tailor-exit-descriptor %edx 0x10)
12577     #
12578     (write _test-input-stream "fn foo {\n")
12579     (write _test-input-stream "  var a: (handle int)\n")
12580     (write _test-input-stream "  read-from-stream a, 0\n")
12581     (write _test-input-stream "}\n")
12582     # convert
12583     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12584     # registers except esp clobbered at this point
12585     # restore ed
12586     89/<- %edx 4/r32/esp
12587     (flush _test-output-buffered-file)
12588     (flush _test-error-buffered-file)
12589 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12595     # check output
12596     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
12597     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type: error message")
12598     # check that stop(1) was called
12599     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
12600     # don't restore from ebp
12601     81 0/subop/add %esp 8/imm32
12602     # . epilogue
12603     5d/pop-to-ebp
12604     c3/return
12605 
12606 test-read-from-stream-with-non-stream-compound-base-type-2:
12607     # . prologue
12608     55/push-ebp
12609     89/<- %ebp 4/r32/esp
12610     # setup
12611     (clear-stream _test-input-stream)
12612     (clear-stream $_test-input-buffered-file->buffer)
12613     (clear-stream _test-output-stream)
12614     (clear-stream $_test-output-buffered-file->buffer)
12615     (clear-stream _test-error-stream)
12616     (clear-stream $_test-error-buffered-file->buffer)
12617     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12618     68/push 0/imm32
12619     68/push 0/imm32
12620     89/<- %edx 4/r32/esp
12621     (tailor-exit-descriptor %edx 0x10)
12622     #
12623     (write _test-input-stream "fn foo {\n")
12624     (write _test-input-stream "  var a: (addr int)\n")
12625     (write _test-input-stream "  read-from-stream a, 0\n")
12626     (write _test-input-stream "}\n")
12627     # convert
12628     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12629     # registers except esp clobbered at this point
12630     # restore ed
12631     89/<- %edx 4/r32/esp
12632     (flush _test-output-buffered-file)
12633     (flush _test-error-buffered-file)
12634 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12640     # check output
12641     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
12642     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message")
12643     # check that stop(1) was called
12644     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
12645     # don't restore from ebp
12646     81 0/subop/add %esp 8/imm32
12647     # . epilogue
12648     5d/pop-to-ebp
12649     c3/return
12650 
12651 test-read-from-stream-with-stream-atom-base-type:
12652     # . prologue
12653     55/push-ebp
12654     89/<- %ebp 4/r32/esp
12655     # setup
12656     (clear-stream _test-input-stream)
12657     (clear-stream $_test-input-buffered-file->buffer)
12658     (clear-stream _test-output-stream)
12659     (clear-stream $_test-output-buffered-file->buffer)
12660     (clear-stream _test-error-stream)
12661     (clear-stream $_test-error-buffered-file->buffer)
12662     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12663     68/push 0/imm32
12664     68/push 0/imm32
12665     89/<- %edx 4/r32/esp
12666     (tailor-exit-descriptor %edx 0x10)
12667     #
12668     (write _test-input-stream "fn foo {\n")
12669     (write _test-input-stream "  var a: stream\n")
12670     (write _test-input-stream "  read-from-stream a, 0\n")
12671     (write _test-input-stream "}\n")
12672     # convert
12673     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12674     # registers except esp clobbered at this point
12675     # restore ed
12676     89/<- %edx 4/r32/esp
12677     (flush _test-output-buffered-file)
12678     (flush _test-error-buffered-file)
12679 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12685     # check output
12686     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
12687     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-stream-atom-base-type: error message")
12688     # check that stop(1) was called
12689     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
12690     # don't restore from ebp
12691     81 0/subop/add %esp 8/imm32
12692     # . epilogue
12693     5d/pop-to-ebp
12694     c3/return
12695 
12696 test-read-from-stream-with-wrong-index-type:
12697     # . prologue
12698     55/push-ebp
12699     89/<- %ebp 4/r32/esp
12700     # setup
12701     (clear-stream _test-input-stream)
12702     (clear-stream $_test-input-buffered-file->buffer)
12703     (clear-stream _test-output-stream)
12704     (clear-stream $_test-output-buffered-file->buffer)
12705     (clear-stream _test-error-stream)
12706     (clear-stream $_test-error-buffered-file->buffer)
12707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12708     68/push 0/imm32
12709     68/push 0/imm32
12710     89/<- %edx 4/r32/esp
12711     (tailor-exit-descriptor %edx 0x10)
12712     #
12713     (write _test-input-stream "fn foo {\n")
12714     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12715     (write _test-input-stream "  var b: boolean\n")
12716     (write _test-input-stream "  read-from-stream a, b\n")
12717     (write _test-input-stream "}\n")
12718     # convert
12719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12720     # registers except esp clobbered at this point
12721     # restore ed
12722     89/<- %edx 4/r32/esp
12723     (flush _test-output-buffered-file)
12724     (flush _test-error-buffered-file)
12725 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12731     # check output
12732     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
12733     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: target 'b' must be an addr"  "F - test-read-from-stream-with-wrong-index-type: error message")
12734     # check that stop(1) was called
12735     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
12736     # don't restore from ebp
12737     81 0/subop/add %esp 8/imm32
12738     # . epilogue
12739     5d/pop-to-ebp
12740     c3/return
12741 
12742 test-read-from-stream-with-no-inouts:
12743     # . prologue
12744     55/push-ebp
12745     89/<- %ebp 4/r32/esp
12746     # setup
12747     (clear-stream _test-input-stream)
12748     (clear-stream $_test-input-buffered-file->buffer)
12749     (clear-stream _test-output-stream)
12750     (clear-stream $_test-output-buffered-file->buffer)
12751     (clear-stream _test-error-stream)
12752     (clear-stream $_test-error-buffered-file->buffer)
12753     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12754     68/push 0/imm32
12755     68/push 0/imm32
12756     89/<- %edx 4/r32/esp
12757     (tailor-exit-descriptor %edx 0x10)
12758     #
12759     (write _test-input-stream "fn foo {\n")
12760     (write _test-input-stream "  read-from-stream\n")
12761     (write _test-input-stream "}\n")
12762     # convert
12763     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12764     # registers except esp clobbered at this point
12765     # restore ed
12766     89/<- %edx 4/r32/esp
12767     (flush _test-output-buffered-file)
12768     (flush _test-error-buffered-file)
12769 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12775     # check output
12776     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
12777     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-no-inouts: error message")
12778     # check that stop(1) was called
12779     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
12780     # don't restore from ebp
12781     81 0/subop/add %esp 8/imm32
12782     # . epilogue
12783     5d/pop-to-ebp
12784     c3/return
12785 
12786 test-read-from-stream-with-too-few-inouts:
12787     # . prologue
12788     55/push-ebp
12789     89/<- %ebp 4/r32/esp
12790     # setup
12791     (clear-stream _test-input-stream)
12792     (clear-stream $_test-input-buffered-file->buffer)
12793     (clear-stream _test-output-stream)
12794     (clear-stream $_test-output-buffered-file->buffer)
12795     (clear-stream _test-error-stream)
12796     (clear-stream $_test-error-buffered-file->buffer)
12797     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12798     68/push 0/imm32
12799     68/push 0/imm32
12800     89/<- %edx 4/r32/esp
12801     (tailor-exit-descriptor %edx 0x10)
12802     #
12803     (write _test-input-stream "fn foo {\n")
12804     (write _test-input-stream "  var a: (addr stream int)\n")
12805     (write _test-input-stream "  read-from-stream a\n")
12806     (write _test-input-stream "}\n")
12807     # convert
12808     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12809     # registers except esp clobbered at this point
12810     # restore ed
12811     89/<- %edx 4/r32/esp
12812     (flush _test-output-buffered-file)
12813     (flush _test-error-buffered-file)
12814 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12820     # check output
12821     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
12822     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-too-few-inouts: error message")
12823     # check that stop(1) was called
12824     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
12825     # don't restore from ebp
12826     81 0/subop/add %esp 8/imm32
12827     # . epilogue
12828     5d/pop-to-ebp
12829     c3/return
12830 
12831 test-read-from-stream-with-too-many-inouts:
12832     # . prologue
12833     55/push-ebp
12834     89/<- %ebp 4/r32/esp
12835     # setup
12836     (clear-stream _test-input-stream)
12837     (clear-stream $_test-input-buffered-file->buffer)
12838     (clear-stream _test-output-stream)
12839     (clear-stream $_test-output-buffered-file->buffer)
12840     (clear-stream _test-error-stream)
12841     (clear-stream $_test-error-buffered-file->buffer)
12842     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12843     68/push 0/imm32
12844     68/push 0/imm32
12845     89/<- %edx 4/r32/esp
12846     (tailor-exit-descriptor %edx 0x10)
12847     #
12848     (write _test-input-stream "fn foo {\n")
12849     (write _test-input-stream "  var a: (addr stream int)\n")
12850     (write _test-input-stream "  var b: (addr int)\n")
12851     (write _test-input-stream "  read-from-stream a, b, 0\n")
12852     (write _test-input-stream "}\n")
12853     # convert
12854     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12855     # registers except esp clobbered at this point
12856     # restore ed
12857     89/<- %edx 4/r32/esp
12858     (flush _test-output-buffered-file)
12859     (flush _test-error-buffered-file)
12860 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12866     # check output
12867     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
12868     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too many inouts (2 required)"  "F - test-read-from-stream-with-too-many-inouts: error message")
12869     # check that stop(1) was called
12870     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
12871     # don't restore from ebp
12872     81 0/subop/add %esp 8/imm32
12873     # . epilogue
12874     5d/pop-to-ebp
12875     c3/return
12876 
12877 test-read-from-stream-with-output:
12878     # . prologue
12879     55/push-ebp
12880     89/<- %ebp 4/r32/esp
12881     # setup
12882     (clear-stream _test-input-stream)
12883     (clear-stream $_test-input-buffered-file->buffer)
12884     (clear-stream _test-output-stream)
12885     (clear-stream $_test-output-buffered-file->buffer)
12886     (clear-stream _test-error-stream)
12887     (clear-stream $_test-error-buffered-file->buffer)
12888     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12889     68/push 0/imm32
12890     68/push 0/imm32
12891     89/<- %edx 4/r32/esp
12892     (tailor-exit-descriptor %edx 0x10)
12893     #
12894     (write _test-input-stream "fn foo {\n")
12895     (write _test-input-stream "  var a: (addr stream int)\n")
12896     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12897     (write _test-input-stream "  b <- read-from-stream a, b\n")
12898     (write _test-input-stream "}\n")
12899     # convert
12900     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12901     # registers except esp clobbered at this point
12902     # restore ed
12903     89/<- %edx 4/r32/esp
12904     (flush _test-output-buffered-file)
12905     (flush _test-error-buffered-file)
12906 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
12912     # check output
12913     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
12914     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: unexpected output"  "F - test-read-from-stream-with-output: error message")
12915     # check that stop(1) was called
12916     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
12917     # don't restore from ebp
12918     81 0/subop/add %esp 8/imm32
12919     # . epilogue
12920     5d/pop-to-ebp
12921     c3/return
12922 
12923 test-convert-write-to-stream:
12924     # . prologue
12925     55/push-ebp
12926     89/<- %ebp 4/r32/esp
12927     # setup
12928     (clear-stream _test-input-stream)
12929     (clear-stream $_test-input-buffered-file->buffer)
12930     (clear-stream _test-output-stream)
12931     (clear-stream $_test-output-buffered-file->buffer)
12932     #
12933     (write _test-input-stream "fn foo {\n")
12934     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
12935     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
12936     (write _test-input-stream "  write-to-stream s, o\n")
12937     (write _test-input-stream "}\n")
12938     # convert
12939     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12940     # registers except esp clobbered at this point
12941     # restore ed
12942     89/<- %edx 4/r32/esp
12943     (flush _test-output-buffered-file)
12944     (flush _test-error-buffered-file)
12945 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
12951     # check output
12952     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
12953     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
12954     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
12955     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
12956     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
12957     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
12958     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
12959     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
12960     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
12961     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
12962     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
12963     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
12964     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
12965     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
12966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
12967     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
12968     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
12969     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
12970     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
12971     # . epilogue
12972     89/<- %esp 5/r32/ebp
12973     5d/pop-to-ebp
12974     c3/return
12975 
12976 test-convert-write-to-stream-with-correct-payload-size:
12977     # . prologue
12978     55/push-ebp
12979     89/<- %ebp 4/r32/esp
12980     # setup
12981     (clear-stream _test-input-stream)
12982     (clear-stream $_test-input-buffered-file->buffer)
12983     (clear-stream _test-output-stream)
12984     (clear-stream $_test-output-buffered-file->buffer)
12985     #
12986     (write _test-input-stream "fn foo {\n")
12987     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
12988     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
12989     (write _test-input-stream "  write-to-stream s, o\n")
12990     (write _test-input-stream "}\n")
12991     # convert
12992     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12993     # registers except esp clobbered at this point
12994     # restore ed
12995     89/<- %edx 4/r32/esp
12996     (flush _test-output-buffered-file)
12997     (flush _test-error-buffered-file)
12998 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13004     # check output
13005     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
13006     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
13007     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
13008     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
13009     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
13010     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
13011     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
13012     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/7")
13013     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
13014     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/9")
13015     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000008)"  "F - test-convert-write-to-stream-with-correct-payload-size/10")
13016     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
13017     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
13018     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
13019     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
13020     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
13021     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
13022     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
13023     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
13024     # . epilogue
13025     89/<- %esp 5/r32/ebp
13026     5d/pop-to-ebp
13027     c3/return
13028 
13029 test-write-to-stream-with-non-stream-atom-base-type:
13030     # . prologue
13031     55/push-ebp
13032     89/<- %ebp 4/r32/esp
13033     # setup
13034     (clear-stream _test-input-stream)
13035     (clear-stream $_test-input-buffered-file->buffer)
13036     (clear-stream _test-output-stream)
13037     (clear-stream $_test-output-buffered-file->buffer)
13038     (clear-stream _test-error-stream)
13039     (clear-stream $_test-error-buffered-file->buffer)
13040     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13041     68/push 0/imm32
13042     68/push 0/imm32
13043     89/<- %edx 4/r32/esp
13044     (tailor-exit-descriptor %edx 0x10)
13045     #
13046     (write _test-input-stream "fn foo {\n")
13047     (write _test-input-stream "  var a: int\n")
13048     (write _test-input-stream "  write-to-stream a, 0\n")
13049     (write _test-input-stream "}\n")
13050     # convert
13051     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13052     # registers except esp clobbered at this point
13053     # restore ed
13054     89/<- %edx 4/r32/esp
13055     (flush _test-output-buffered-file)
13056     (flush _test-error-buffered-file)
13057 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13063     # check output
13064     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
13065     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-atom-base-type: error message")
13066     # check that stop(1) was called
13067     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
13068     # don't restore from ebp
13069     81 0/subop/add %esp 8/imm32
13070     # . epilogue
13071     5d/pop-to-ebp
13072     c3/return
13073 
13074 test-write-to-stream-with-non-stream-compound-base-type:
13075     # . prologue
13076     55/push-ebp
13077     89/<- %ebp 4/r32/esp
13078     # setup
13079     (clear-stream _test-input-stream)
13080     (clear-stream $_test-input-buffered-file->buffer)
13081     (clear-stream _test-output-stream)
13082     (clear-stream $_test-output-buffered-file->buffer)
13083     (clear-stream _test-error-stream)
13084     (clear-stream $_test-error-buffered-file->buffer)
13085     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13086     68/push 0/imm32
13087     68/push 0/imm32
13088     89/<- %edx 4/r32/esp
13089     (tailor-exit-descriptor %edx 0x10)
13090     #
13091     (write _test-input-stream "fn foo {\n")
13092     (write _test-input-stream "  var a: (handle int)\n")
13093     (write _test-input-stream "  write-to-stream a, 0\n")
13094     (write _test-input-stream "}\n")
13095     # convert
13096     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13097     # registers except esp clobbered at this point
13098     # restore ed
13099     89/<- %edx 4/r32/esp
13100     (flush _test-output-buffered-file)
13101     (flush _test-error-buffered-file)
13102 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13108     # check output
13109     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
13110     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type: error message")
13111     # check that stop(1) was called
13112     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
13113     # don't restore from ebp
13114     81 0/subop/add %esp 8/imm32
13115     # . epilogue
13116     5d/pop-to-ebp
13117     c3/return
13118 
13119 test-write-to-stream-with-non-stream-compound-base-type-2:
13120     # . prologue
13121     55/push-ebp
13122     89/<- %ebp 4/r32/esp
13123     # setup
13124     (clear-stream _test-input-stream)
13125     (clear-stream $_test-input-buffered-file->buffer)
13126     (clear-stream _test-output-stream)
13127     (clear-stream $_test-output-buffered-file->buffer)
13128     (clear-stream _test-error-stream)
13129     (clear-stream $_test-error-buffered-file->buffer)
13130     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13131     68/push 0/imm32
13132     68/push 0/imm32
13133     89/<- %edx 4/r32/esp
13134     (tailor-exit-descriptor %edx 0x10)
13135     #
13136     (write _test-input-stream "fn foo {\n")
13137     (write _test-input-stream "  var a: (addr int)\n")
13138     (write _test-input-stream "  write-to-stream a, 0\n")
13139     (write _test-input-stream "}\n")
13140     # convert
13141     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13142     # registers except esp clobbered at this point
13143     # restore ed
13144     89/<- %edx 4/r32/esp
13145     (flush _test-output-buffered-file)
13146     (flush _test-error-buffered-file)
13147 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13153     # check output
13154     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
13155     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message")
13156     # check that stop(1) was called
13157     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
13158     # don't restore from ebp
13159     81 0/subop/add %esp 8/imm32
13160     # . epilogue
13161     5d/pop-to-ebp
13162     c3/return
13163 
13164 test-write-to-stream-with-stream-atom-base-type:
13165     # . prologue
13166     55/push-ebp
13167     89/<- %ebp 4/r32/esp
13168     # setup
13169     (clear-stream _test-input-stream)
13170     (clear-stream $_test-input-buffered-file->buffer)
13171     (clear-stream _test-output-stream)
13172     (clear-stream $_test-output-buffered-file->buffer)
13173     (clear-stream _test-error-stream)
13174     (clear-stream $_test-error-buffered-file->buffer)
13175     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13176     68/push 0/imm32
13177     68/push 0/imm32
13178     89/<- %edx 4/r32/esp
13179     (tailor-exit-descriptor %edx 0x10)
13180     #
13181     (write _test-input-stream "fn foo {\n")
13182     (write _test-input-stream "  var a: stream\n")
13183     (write _test-input-stream "  write-to-stream a, 0\n")
13184     (write _test-input-stream "}\n")
13185     # convert
13186     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13187     # registers except esp clobbered at this point
13188     # restore ed
13189     89/<- %edx 4/r32/esp
13190     (flush _test-output-buffered-file)
13191     (flush _test-error-buffered-file)
13192 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13198     # check output
13199     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
13200     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-stream-atom-base-type: error message")
13201     # check that stop(1) was called
13202     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
13203     # don't restore from ebp
13204     81 0/subop/add %esp 8/imm32
13205     # . epilogue
13206     5d/pop-to-ebp
13207     c3/return
13208 
13209 test-write-to-stream-with-wrong-index-type:
13210     # . prologue
13211     55/push-ebp
13212     89/<- %ebp 4/r32/esp
13213     # setup
13214     (clear-stream _test-input-stream)
13215     (clear-stream $_test-input-buffered-file->buffer)
13216     (clear-stream _test-output-stream)
13217     (clear-stream $_test-output-buffered-file->buffer)
13218     (clear-stream _test-error-stream)
13219     (clear-stream $_test-error-buffered-file->buffer)
13220     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13221     68/push 0/imm32
13222     68/push 0/imm32
13223     89/<- %edx 4/r32/esp
13224     (tailor-exit-descriptor %edx 0x10)
13225     #
13226     (write _test-input-stream "fn foo {\n")
13227     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
13228     (write _test-input-stream "  var b: boolean\n")
13229     (write _test-input-stream "  write-to-stream a, b\n")
13230     (write _test-input-stream "}\n")
13231     # convert
13232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13233     # registers except esp clobbered at this point
13234     # restore ed
13235     89/<- %edx 4/r32/esp
13236     (flush _test-output-buffered-file)
13237     (flush _test-error-buffered-file)
13238 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13244     # check output
13245     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
13246     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: target 'b' must be an addr"  "F - test-write-to-stream-with-wrong-index-type: error message")
13247     # check that stop(1) was called
13248     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
13249     # don't restore from ebp
13250     81 0/subop/add %esp 8/imm32
13251     # . epilogue
13252     5d/pop-to-ebp
13253     c3/return
13254 
13255 test-write-to-stream-with-no-inouts:
13256     # . prologue
13257     55/push-ebp
13258     89/<- %ebp 4/r32/esp
13259     # setup
13260     (clear-stream _test-input-stream)
13261     (clear-stream $_test-input-buffered-file->buffer)
13262     (clear-stream _test-output-stream)
13263     (clear-stream $_test-output-buffered-file->buffer)
13264     (clear-stream _test-error-stream)
13265     (clear-stream $_test-error-buffered-file->buffer)
13266     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13267     68/push 0/imm32
13268     68/push 0/imm32
13269     89/<- %edx 4/r32/esp
13270     (tailor-exit-descriptor %edx 0x10)
13271     #
13272     (write _test-input-stream "fn foo {\n")
13273     (write _test-input-stream "  write-to-stream\n")
13274     (write _test-input-stream "}\n")
13275     # convert
13276     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13277     # registers except esp clobbered at this point
13278     # restore ed
13279     89/<- %edx 4/r32/esp
13280     (flush _test-output-buffered-file)
13281     (flush _test-error-buffered-file)
13282 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13288     # check output
13289     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
13290     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-no-inouts: error message")
13291     # check that stop(1) was called
13292     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
13293     # don't restore from ebp
13294     81 0/subop/add %esp 8/imm32
13295     # . epilogue
13296     5d/pop-to-ebp
13297     c3/return
13298 
13299 test-write-to-stream-with-too-few-inouts:
13300     # . prologue
13301     55/push-ebp
13302     89/<- %ebp 4/r32/esp
13303     # setup
13304     (clear-stream _test-input-stream)
13305     (clear-stream $_test-input-buffered-file->buffer)
13306     (clear-stream _test-output-stream)
13307     (clear-stream $_test-output-buffered-file->buffer)
13308     (clear-stream _test-error-stream)
13309     (clear-stream $_test-error-buffered-file->buffer)
13310     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13311     68/push 0/imm32
13312     68/push 0/imm32
13313     89/<- %edx 4/r32/esp
13314     (tailor-exit-descriptor %edx 0x10)
13315     #
13316     (write _test-input-stream "fn foo {\n")
13317     (write _test-input-stream "  var a: (addr stream int)\n")
13318     (write _test-input-stream "  write-to-stream a\n")
13319     (write _test-input-stream "}\n")
13320     # convert
13321     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13322     # registers except esp clobbered at this point
13323     # restore ed
13324     89/<- %edx 4/r32/esp
13325     (flush _test-output-buffered-file)
13326     (flush _test-error-buffered-file)
13327 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13333     # check output
13334     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
13335     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-too-few-inouts: error message")
13336     # check that stop(1) was called
13337     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
13338     # don't restore from ebp
13339     81 0/subop/add %esp 8/imm32
13340     # . epilogue
13341     5d/pop-to-ebp
13342     c3/return
13343 
13344 test-write-to-stream-with-too-many-inouts:
13345     # . prologue
13346     55/push-ebp
13347     89/<- %ebp 4/r32/esp
13348     # setup
13349     (clear-stream _test-input-stream)
13350     (clear-stream $_test-input-buffered-file->buffer)
13351     (clear-stream _test-output-stream)
13352     (clear-stream $_test-output-buffered-file->buffer)
13353     (clear-stream _test-error-stream)
13354     (clear-stream $_test-error-buffered-file->buffer)
13355     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13356     68/push 0/imm32
13357     68/push 0/imm32
13358     89/<- %edx 4/r32/esp
13359     (tailor-exit-descriptor %edx 0x10)
13360     #
13361     (write _test-input-stream "fn foo {\n")
13362     (write _test-input-stream "  var a: (addr stream int)\n")
13363     (write _test-input-stream "  var b: (addr int)\n")
13364     (write _test-input-stream "  write-to-stream a, b, 0\n")
13365     (write _test-input-stream "}\n")
13366     # convert
13367     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13368     # registers except esp clobbered at this point
13369     # restore ed
13370     89/<- %edx 4/r32/esp
13371     (flush _test-output-buffered-file)
13372     (flush _test-error-buffered-file)
13373 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13379     # check output
13380     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
13381     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too many inouts (2 required)"  "F - test-write-to-stream-with-too-many-inouts: error message")
13382     # check that stop(1) was called
13383     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
13384     # don't restore from ebp
13385     81 0/subop/add %esp 8/imm32
13386     # . epilogue
13387     5d/pop-to-ebp
13388     c3/return
13389 
13390 test-write-to-stream-with-output:
13391     # . prologue
13392     55/push-ebp
13393     89/<- %ebp 4/r32/esp
13394     # setup
13395     (clear-stream _test-input-stream)
13396     (clear-stream $_test-input-buffered-file->buffer)
13397     (clear-stream _test-output-stream)
13398     (clear-stream $_test-output-buffered-file->buffer)
13399     (clear-stream _test-error-stream)
13400     (clear-stream $_test-error-buffered-file->buffer)
13401     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13402     68/push 0/imm32
13403     68/push 0/imm32
13404     89/<- %edx 4/r32/esp
13405     (tailor-exit-descriptor %edx 0x10)
13406     #
13407     (write _test-input-stream "fn foo {\n")
13408     (write _test-input-stream "  var a: (addr stream int)\n")
13409     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
13410     (write _test-input-stream "  b <- write-to-stream a, b\n")
13411     (write _test-input-stream "}\n")
13412     # convert
13413     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13414     # registers except esp clobbered at this point
13415     # restore ed
13416     89/<- %edx 4/r32/esp
13417     (flush _test-output-buffered-file)
13418     (flush _test-error-buffered-file)
13419 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13425     # check output
13426     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
13427     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: unexpected output"  "F - test-write-to-stream-with-output: error message")
13428     # check that stop(1) was called
13429     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
13430     # don't restore from ebp
13431     81 0/subop/add %esp 8/imm32
13432     # . epilogue
13433     5d/pop-to-ebp
13434     c3/return
13435 
13436 test-length-with-non-array-atom-base-type:
13437     # . prologue
13438     55/push-ebp
13439     89/<- %ebp 4/r32/esp
13440     # setup
13441     (clear-stream _test-input-stream)
13442     (clear-stream $_test-input-buffered-file->buffer)
13443     (clear-stream _test-output-stream)
13444     (clear-stream $_test-output-buffered-file->buffer)
13445     (clear-stream _test-error-stream)
13446     (clear-stream $_test-error-buffered-file->buffer)
13447     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13448     68/push 0/imm32
13449     68/push 0/imm32
13450     89/<- %edx 4/r32/esp
13451     (tailor-exit-descriptor %edx 0x10)
13452     #
13453     (write _test-input-stream "fn foo {\n")
13454     (write _test-input-stream "  var a: int\n")
13455     (write _test-input-stream "  var c/ecx: int <- length a\n")
13456     (write _test-input-stream "}\n")
13457     # convert
13458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13459     # registers except esp clobbered at this point
13460     # restore ed
13461     89/<- %edx 4/r32/esp
13462     (flush _test-output-buffered-file)
13463     (flush _test-error-buffered-file)
13464 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13470     # check output
13471     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
13472     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-atom-base-type: error message")
13473     # check that stop(1) was called
13474     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
13475     # don't restore from ebp
13476     81 0/subop/add %esp 8/imm32
13477     # . epilogue
13478     5d/pop-to-ebp
13479     c3/return
13480 
13481 test-length-with-non-array-compound-base-type:
13482     # . prologue
13483     55/push-ebp
13484     89/<- %ebp 4/r32/esp
13485     # setup
13486     (clear-stream _test-input-stream)
13487     (clear-stream $_test-input-buffered-file->buffer)
13488     (clear-stream _test-output-stream)
13489     (clear-stream $_test-output-buffered-file->buffer)
13490     (clear-stream _test-error-stream)
13491     (clear-stream $_test-error-buffered-file->buffer)
13492     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13493     68/push 0/imm32
13494     68/push 0/imm32
13495     89/<- %edx 4/r32/esp
13496     (tailor-exit-descriptor %edx 0x10)
13497     #
13498     (write _test-input-stream "fn foo {\n")
13499     (write _test-input-stream "  var a: (handle int)\n")
13500     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13501     (write _test-input-stream "}\n")
13502     # convert
13503     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13504     # registers except esp clobbered at this point
13505     # restore ed
13506     89/<- %edx 4/r32/esp
13507     (flush _test-output-buffered-file)
13508     (flush _test-error-buffered-file)
13509 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13515     # check output
13516     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
13517     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type: error message")
13518     # check that stop(1) was called
13519     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
13520     # don't restore from ebp
13521     81 0/subop/add %esp 8/imm32
13522     # . epilogue
13523     5d/pop-to-ebp
13524     c3/return
13525 
13526 test-length-with-non-array-compound-base-type-2:
13527     # . prologue
13528     55/push-ebp
13529     89/<- %ebp 4/r32/esp
13530     # setup
13531     (clear-stream _test-input-stream)
13532     (clear-stream $_test-input-buffered-file->buffer)
13533     (clear-stream _test-output-stream)
13534     (clear-stream $_test-output-buffered-file->buffer)
13535     (clear-stream _test-error-stream)
13536     (clear-stream $_test-error-buffered-file->buffer)
13537     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13538     68/push 0/imm32
13539     68/push 0/imm32
13540     89/<- %edx 4/r32/esp
13541     (tailor-exit-descriptor %edx 0x10)
13542     #
13543     (write _test-input-stream "fn foo {\n")
13544     (write _test-input-stream "  var a: (addr int)\n")
13545     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
13546     (write _test-input-stream "}\n")
13547     # convert
13548     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13549     # registers except esp clobbered at this point
13550     # restore ed
13551     89/<- %edx 4/r32/esp
13552     (flush _test-output-buffered-file)
13553     (flush _test-error-buffered-file)
13554 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13560     # check output
13561     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
13562     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type-2: error message")
13563     # check that stop(1) was called
13564     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
13565     # don't restore from ebp
13566     81 0/subop/add %esp 8/imm32
13567     # . epilogue
13568     5d/pop-to-ebp
13569     c3/return
13570 
13571 test-length-with-array-atom-base-type:
13572     # . prologue
13573     55/push-ebp
13574     89/<- %ebp 4/r32/esp
13575     # setup
13576     (clear-stream _test-input-stream)
13577     (clear-stream $_test-input-buffered-file->buffer)
13578     (clear-stream _test-output-stream)
13579     (clear-stream $_test-output-buffered-file->buffer)
13580     (clear-stream _test-error-stream)
13581     (clear-stream $_test-error-buffered-file->buffer)
13582     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13583     68/push 0/imm32
13584     68/push 0/imm32
13585     89/<- %edx 4/r32/esp
13586     (tailor-exit-descriptor %edx 0x10)
13587     #
13588     (write _test-input-stream "fn foo {\n")
13589     (write _test-input-stream "  var a: array\n")
13590     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13591     (write _test-input-stream "}\n")
13592     # convert
13593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13594     # registers except esp clobbered at this point
13595     # restore ed
13596     89/<- %edx 4/r32/esp
13597     (flush _test-output-buffered-file)
13598     (flush _test-error-buffered-file)
13599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13605     # check output
13606     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
13607     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: array 'a' must specify the type of its elements"  "F - test-length-with-array-atom-base-type: error message")
13608     # check that stop(1) was called
13609     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
13610     # don't restore from ebp
13611     81 0/subop/add %esp 8/imm32
13612     # . epilogue
13613     5d/pop-to-ebp
13614     c3/return
13615 
13616 test-length-with-addr-base-on-stack:
13617     # . prologue
13618     55/push-ebp
13619     89/<- %ebp 4/r32/esp
13620     # setup
13621     (clear-stream _test-input-stream)
13622     (clear-stream $_test-input-buffered-file->buffer)
13623     (clear-stream _test-output-stream)
13624     (clear-stream $_test-output-buffered-file->buffer)
13625     (clear-stream _test-error-stream)
13626     (clear-stream $_test-error-buffered-file->buffer)
13627     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13628     68/push 0/imm32
13629     68/push 0/imm32
13630     89/<- %edx 4/r32/esp
13631     (tailor-exit-descriptor %edx 0x10)
13632     #
13633     (write _test-input-stream "fn foo {\n")
13634     (write _test-input-stream "  var a: (addr array int)\n")
13635     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
13636     (write _test-input-stream "}\n")
13637     # convert
13638     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13639     # registers except esp clobbered at this point
13640     # restore ed
13641     89/<- %edx 4/r32/esp
13642     (flush _test-output-buffered-file)
13643     (flush _test-error-buffered-file)
13644 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13650     # check output
13651     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
13652     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is an addr to an array, and so must live in a register"  "F - test-length-with-addr-base-on-stack: error message")
13653     # check that stop(1) was called
13654     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
13655     # don't restore from ebp
13656     81 0/subop/add %esp 8/imm32
13657     # . epilogue
13658     5d/pop-to-ebp
13659     c3/return
13660 
13661 test-length-with-wrong-output-type:
13662     # . prologue
13663     55/push-ebp
13664     89/<- %ebp 4/r32/esp
13665     # setup
13666     (clear-stream _test-input-stream)
13667     (clear-stream $_test-input-buffered-file->buffer)
13668     (clear-stream _test-output-stream)
13669     (clear-stream $_test-output-buffered-file->buffer)
13670     (clear-stream _test-error-stream)
13671     (clear-stream $_test-error-buffered-file->buffer)
13672     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13673     68/push 0/imm32
13674     68/push 0/imm32
13675     89/<- %edx 4/r32/esp
13676     (tailor-exit-descriptor %edx 0x10)
13677     #
13678     (write _test-input-stream "fn foo {\n")
13679     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
13680     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
13681     (write _test-input-stream "}\n")
13682     # convert
13683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13684     # registers except esp clobbered at this point
13685     # restore ed
13686     89/<- %edx 4/r32/esp
13687     (flush _test-output-buffered-file)
13688     (flush _test-error-buffered-file)
13689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13695     # check output
13696     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
13697     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-type: error message")
13698     # check that stop(1) was called
13699     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
13700     # don't restore from ebp
13701     81 0/subop/add %esp 8/imm32
13702     # . epilogue
13703     5d/pop-to-ebp
13704     c3/return
13705 
13706 test-length-with-wrong-output-compound-type:
13707     # . prologue
13708     55/push-ebp
13709     89/<- %ebp 4/r32/esp
13710     # setup
13711     (clear-stream _test-input-stream)
13712     (clear-stream $_test-input-buffered-file->buffer)
13713     (clear-stream _test-output-stream)
13714     (clear-stream $_test-output-buffered-file->buffer)
13715     (clear-stream _test-error-stream)
13716     (clear-stream $_test-error-buffered-file->buffer)
13717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13718     68/push 0/imm32
13719     68/push 0/imm32
13720     89/<- %edx 4/r32/esp
13721     (tailor-exit-descriptor %edx 0x10)
13722     #
13723     (write _test-input-stream "fn foo {\n")
13724     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
13725     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
13726     (write _test-input-stream "}\n")
13727     # convert
13728     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13729     # registers except esp clobbered at this point
13730     # restore ed
13731     89/<- %edx 4/r32/esp
13732     (flush _test-output-buffered-file)
13733     (flush _test-error-buffered-file)
13734 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13740     # check output
13741     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
13742     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-compound-type: error message")
13743     # check that stop(1) was called
13744     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
13745     # don't restore from ebp
13746     81 0/subop/add %esp 8/imm32
13747     # . epilogue
13748     5d/pop-to-ebp
13749     c3/return
13750 
13751 test-length-with-no-inouts:
13752     # . prologue
13753     55/push-ebp
13754     89/<- %ebp 4/r32/esp
13755     # setup
13756     (clear-stream _test-input-stream)
13757     (clear-stream $_test-input-buffered-file->buffer)
13758     (clear-stream _test-output-stream)
13759     (clear-stream $_test-output-buffered-file->buffer)
13760     (clear-stream _test-error-stream)
13761     (clear-stream $_test-error-buffered-file->buffer)
13762     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13763     68/push 0/imm32
13764     68/push 0/imm32
13765     89/<- %edx 4/r32/esp
13766     (tailor-exit-descriptor %edx 0x10)
13767     #
13768     (write _test-input-stream "fn foo {\n")
13769     (write _test-input-stream "  var c/ecx: int <- length\n")
13770     (write _test-input-stream "}\n")
13771     # convert
13772     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13773     # registers except esp clobbered at this point
13774     # restore ed
13775     89/<- %edx 4/r32/esp
13776     (flush _test-output-buffered-file)
13777     (flush _test-error-buffered-file)
13778 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13784     # check output
13785     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
13786     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too few inouts (1 required)"  "F - test-length-with-no-inouts: error message")
13787     # check that stop(1) was called
13788     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
13789     # don't restore from ebp
13790     81 0/subop/add %esp 8/imm32
13791     # . epilogue
13792     5d/pop-to-ebp
13793     c3/return
13794 
13795 test-length-with-too-many-inouts:
13796     # . prologue
13797     55/push-ebp
13798     89/<- %ebp 4/r32/esp
13799     # setup
13800     (clear-stream _test-input-stream)
13801     (clear-stream $_test-input-buffered-file->buffer)
13802     (clear-stream _test-output-stream)
13803     (clear-stream $_test-output-buffered-file->buffer)
13804     (clear-stream _test-error-stream)
13805     (clear-stream $_test-error-buffered-file->buffer)
13806     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13807     68/push 0/imm32
13808     68/push 0/imm32
13809     89/<- %edx 4/r32/esp
13810     (tailor-exit-descriptor %edx 0x10)
13811     #
13812     (write _test-input-stream "fn foo {\n")
13813     (write _test-input-stream "  var a: (array int 3)\n")
13814     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
13815     (write _test-input-stream "}\n")
13816     # convert
13817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13818     # registers except esp clobbered at this point
13819     # restore ed
13820     89/<- %edx 4/r32/esp
13821     (flush _test-output-buffered-file)
13822     (flush _test-error-buffered-file)
13823 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13829     # check output
13830     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
13831     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many inouts (1 required)"  "F - test-length-with-too-many-inouts: error message")
13832     # check that stop(1) was called
13833     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
13834     # don't restore from ebp
13835     81 0/subop/add %esp 8/imm32
13836     # . epilogue
13837     5d/pop-to-ebp
13838     c3/return
13839 
13840 test-length-with-no-output:
13841     # . prologue
13842     55/push-ebp
13843     89/<- %ebp 4/r32/esp
13844     # setup
13845     (clear-stream _test-input-stream)
13846     (clear-stream $_test-input-buffered-file->buffer)
13847     (clear-stream _test-output-stream)
13848     (clear-stream $_test-output-buffered-file->buffer)
13849     (clear-stream _test-error-stream)
13850     (clear-stream $_test-error-buffered-file->buffer)
13851     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13852     68/push 0/imm32
13853     68/push 0/imm32
13854     89/<- %edx 4/r32/esp
13855     (tailor-exit-descriptor %edx 0x10)
13856     #
13857     (write _test-input-stream "fn foo {\n")
13858     (write _test-input-stream "  var a: (array int 3)\n")
13859     (write _test-input-stream "  length a\n")
13860     (write _test-input-stream "}\n")
13861     # convert
13862     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13863     # registers except esp clobbered at this point
13864     # restore ed
13865     89/<- %edx 4/r32/esp
13866     (flush _test-output-buffered-file)
13867     (flush _test-error-buffered-file)
13868 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13874     # check output
13875     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
13876     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
13877     # check that stop(1) was called
13878     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
13879     # don't restore from ebp
13880     81 0/subop/add %esp 8/imm32
13881     # . epilogue
13882     5d/pop-to-ebp
13883     c3/return
13884 
13885 test-length-with-too-many-outputs:
13886     # . prologue
13887     55/push-ebp
13888     89/<- %ebp 4/r32/esp
13889     # setup
13890     (clear-stream _test-input-stream)
13891     (clear-stream $_test-input-buffered-file->buffer)
13892     (clear-stream _test-output-stream)
13893     (clear-stream $_test-output-buffered-file->buffer)
13894     (clear-stream _test-error-stream)
13895     (clear-stream $_test-error-buffered-file->buffer)
13896     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13897     68/push 0/imm32
13898     68/push 0/imm32
13899     89/<- %edx 4/r32/esp
13900     (tailor-exit-descriptor %edx 0x10)
13901     #
13902     (write _test-input-stream "fn foo {\n")
13903     (write _test-input-stream "  var a: (array int 3)\n")
13904     (write _test-input-stream "  var b/eax: int <- copy 0\n")
13905     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
13906     (write _test-input-stream "  b, c <- length a\n")
13907     (write _test-input-stream "}\n")
13908     # convert
13909     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13910     # registers except esp clobbered at this point
13911     # restore ed
13912     89/<- %edx 4/r32/esp
13913     (flush _test-output-buffered-file)
13914     (flush _test-error-buffered-file)
13915 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
13921     # check output
13922     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
13923     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many outputs (1 required)"  "F - test-length-with-too-many-outputs: error message")
13924     # check that stop(1) was called
13925     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
13926     # don't restore from ebp
13927     81 0/subop/add %esp 8/imm32
13928     # . epilogue
13929     5d/pop-to-ebp
13930     c3/return
13931 
13932 test-convert-function-with-return-register-and-local:
13933     # . prologue
13934     55/push-ebp
13935     89/<- %ebp 4/r32/esp
13936     # setup
13937     (clear-stream _test-input-stream)
13938     (clear-stream $_test-input-buffered-file->buffer)
13939     (clear-stream _test-output-stream)
13940     (clear-stream $_test-output-buffered-file->buffer)
13941     #
13942     (write _test-input-stream "fn foo -> _/eax: int {\n")
13943     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13944     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13945     (write _test-input-stream "  return y\n")
13946     (write _test-input-stream "}\n")
13947     # convert
13948     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13949     (flush _test-output-buffered-file)
13950 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
13956     # check output
13957     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
13958     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
13959     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
13960     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
13961     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
13962     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
13963     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
13964     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
13965     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
13966     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
13967     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
13968     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
13969     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local/12")
13970     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
13971     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
13972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
13973     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
13974     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
13975     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
13976     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
13977     # . epilogue
13978     89/<- %esp 5/r32/ebp
13979     5d/pop-to-ebp
13980     c3/return
13981 
13982 test-convert-function-with-return-register-and-local-2:
13983     # . prologue
13984     55/push-ebp
13985     89/<- %ebp 4/r32/esp
13986     # setup
13987     (clear-stream _test-input-stream)
13988     (clear-stream $_test-input-buffered-file->buffer)
13989     (clear-stream _test-output-stream)
13990     (clear-stream $_test-output-buffered-file->buffer)
13991     #
13992     (write _test-input-stream "fn foo -> _/eax: int {\n")
13993     (write _test-input-stream "  var y/eax: int <- copy 3\n")
13994     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
13995     (write _test-input-stream "  return z\n")
13996     (write _test-input-stream "}\n")
13997     # convert
13998     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13999     (flush _test-output-buffered-file)
14000 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14006     # check output
14007     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
14008     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
14009     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
14010     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
14011     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
14012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
14013     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
14014     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local-2/7")
14015     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
14016     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/9")
14017     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
14018     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
14019     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/12")
14020     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local-2/13")
14021     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
14022     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
14023     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
14024     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
14025     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
14026     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
14027     # . epilogue
14028     89/<- %esp 5/r32/ebp
14029     5d/pop-to-ebp
14030     c3/return
14031 
14032 test-convert-function-with-return-float-register-and-local:
14033     # . prologue
14034     55/push-ebp
14035     89/<- %ebp 4/r32/esp
14036     # setup
14037     (clear-stream _test-input-stream)
14038     (clear-stream $_test-input-buffered-file->buffer)
14039     (clear-stream _test-output-stream)
14040     (clear-stream $_test-output-buffered-file->buffer)
14041     #
14042     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
14043     (write _test-input-stream "  var y/eax: int <- copy 3\n")
14044     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
14045     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
14046     (write _test-input-stream "  return g\n")
14047     (write _test-input-stream "}\n")
14048     # convert
14049     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14050     (flush _test-output-buffered-file)
14051 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14057     # check output
14058     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
14059     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
14060     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
14061     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
14062     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
14063     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
14064     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-float-register-and-local/6")  # var y
14065     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-float-register-and-local/7")
14066     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/8")  # var g
14067     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 0/x32"  "F - test-convert-function-with-return-float-register-and-local/9")
14068     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000000/x32"  "F - test-convert-function-with-return-float-register-and-local/10")
14069     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/11")  # var h
14070     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-function-with-return-float-register-and-local/12")
14071     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/13")
14072     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> %xmm0 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/14")  # return g
14073     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
14074     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
14075     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
14076     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"         "F - test-convert-function-with-return-float-register-and-local/18")  # reclaim y
14077     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-float-register-and-local/19")
14078     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
14079     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
14080     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
14081     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
14082     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
14083     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
14084     # . epilogue
14085     89/<- %esp 5/r32/ebp
14086     5d/pop-to-ebp
14087     c3/return
14088 
14089 test-convert-function-with-return-and-local-vars:
14090     # . prologue
14091     55/push-ebp
14092     89/<- %ebp 4/r32/esp
14093     # setup
14094     (clear-stream _test-input-stream)
14095     (clear-stream $_test-input-buffered-file->buffer)
14096     (clear-stream _test-output-stream)
14097     (clear-stream $_test-output-buffered-file->buffer)
14098     #
14099     (write _test-input-stream "fn foo -> _/eax: int {\n")
14100     (write _test-input-stream "  {\n")
14101     (write _test-input-stream "    var x: int\n")
14102     (write _test-input-stream "    {\n")
14103     (write _test-input-stream "      var y: int\n")
14104     (write _test-input-stream "      return y\n")
14105     (write _test-input-stream "      increment x\n")
14106     (write _test-input-stream "    }\n")
14107     (write _test-input-stream "  }\n")
14108     (write _test-input-stream "  return 0\n")
14109     (write _test-input-stream "}\n")
14110     # convert
14111     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14112     (flush _test-output-buffered-file)
14113 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
14119     # check output
14120     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
14121     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
14122     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
14123     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
14124     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
14125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
14126     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
14127     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
14128     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
14129     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
14130     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
14131     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
14132     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
14133     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/13")
14134     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/14")
14135     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
14136     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
14137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
14138     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/18")
14139     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
14140     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
14141     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-and-local-vars/21")
14142     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
14143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
14144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
14145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
14146     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
14147     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
14148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
14149     # . epilogue
14150     89/<- %esp 5/r32/ebp
14151     5d/pop-to-ebp
14152     c3/return
14153 
14154 test-copy-object-with-no-inout:
14155     # . prologue
14156     55/push-ebp
14157     89/<- %ebp 4/r32/esp
14158     # setup
14159     (clear-stream _test-input-stream)
14160     (clear-stream $_test-input-buffered-file->buffer)
14161     (clear-stream _test-output-stream)
14162     (clear-stream $_test-output-buffered-file->buffer)
14163     (clear-stream _test-error-stream)
14164     (clear-stream $_test-error-buffered-file->buffer)
14165     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14166     68/push 0/imm32
14167     68/push 0/imm32
14168     89/<- %edx 4/r32/esp
14169     (tailor-exit-descriptor %edx 0x10)
14170     #
14171     (write _test-input-stream "fn foo {\n")
14172     (write _test-input-stream "  copy-object\n")
14173     (write _test-input-stream "}\n")
14174     # convert
14175     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14176     # registers except esp clobbered at this point
14177     # restore ed
14178     89/<- %edx 4/r32/esp
14179     (flush _test-output-buffered-file)
14180     (flush _test-error-buffered-file)
14181 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14187     # check output
14188     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
14189     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
14190     # check that stop(1) was called
14191     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
14192     # don't restore from ebp
14193     81 0/subop/add %esp 8/imm32
14194     # . epilogue
14195     5d/pop-to-ebp
14196     c3/return
14197 
14198 test-copy-object-with-no-source:
14199     # . prologue
14200     55/push-ebp
14201     89/<- %ebp 4/r32/esp
14202     # setup
14203     (clear-stream _test-input-stream)
14204     (clear-stream $_test-input-buffered-file->buffer)
14205     (clear-stream _test-output-stream)
14206     (clear-stream $_test-output-buffered-file->buffer)
14207     (clear-stream _test-error-stream)
14208     (clear-stream $_test-error-buffered-file->buffer)
14209     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14210     68/push 0/imm32
14211     68/push 0/imm32
14212     89/<- %edx 4/r32/esp
14213     (tailor-exit-descriptor %edx 0x10)
14214     #
14215     (write _test-input-stream "fn foo {\n")
14216     (write _test-input-stream "  var x: (addr int)\n")
14217     (write _test-input-stream "  copy-object x\n")
14218     (write _test-input-stream "}\n")
14219     # convert
14220     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14221     # registers except esp clobbered at this point
14222     # restore ed
14223     89/<- %edx 4/r32/esp
14224     (flush _test-output-buffered-file)
14225     (flush _test-error-buffered-file)
14226 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14232     # check output
14233     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
14234     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-source: error message")
14235     # check that stop(1) was called
14236     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
14237     # don't restore from ebp
14238     81 0/subop/add %esp 8/imm32
14239     # . epilogue
14240     5d/pop-to-ebp
14241     c3/return
14242 
14243 test-copy-object-with-too-many-inouts:
14244     # . prologue
14245     55/push-ebp
14246     89/<- %ebp 4/r32/esp
14247     # setup
14248     (clear-stream _test-input-stream)
14249     (clear-stream $_test-input-buffered-file->buffer)
14250     (clear-stream _test-output-stream)
14251     (clear-stream $_test-output-buffered-file->buffer)
14252     (clear-stream _test-error-stream)
14253     (clear-stream $_test-error-buffered-file->buffer)
14254     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14255     68/push 0/imm32
14256     68/push 0/imm32
14257     89/<- %edx 4/r32/esp
14258     (tailor-exit-descriptor %edx 0x10)
14259     #
14260     (write _test-input-stream "fn foo {\n")
14261     (write _test-input-stream "  var x: (addr boolean)\n")
14262     (write _test-input-stream "  copy-object x, x, x\n")
14263     (write _test-input-stream "}\n")
14264     # convert
14265     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14266     # registers except esp clobbered at this point
14267     # restore ed
14268     89/<- %edx 4/r32/esp
14269     (flush _test-output-buffered-file)
14270     (flush _test-error-buffered-file)
14271 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14277     # check output
14278     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
14279     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-too-many-inouts: error message")
14280     # check that stop(1) was called
14281     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
14282     # don't restore from ebp
14283     81 0/subop/add %esp 8/imm32
14284     # . epilogue
14285     5d/pop-to-ebp
14286     c3/return
14287 
14288 test-copy-object-with-output:
14289     # . prologue
14290     55/push-ebp
14291     89/<- %ebp 4/r32/esp
14292     # setup
14293     (clear-stream _test-input-stream)
14294     (clear-stream $_test-input-buffered-file->buffer)
14295     (clear-stream _test-output-stream)
14296     (clear-stream $_test-output-buffered-file->buffer)
14297     (clear-stream _test-error-stream)
14298     (clear-stream $_test-error-buffered-file->buffer)
14299     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14300     68/push 0/imm32
14301     68/push 0/imm32
14302     89/<- %edx 4/r32/esp
14303     (tailor-exit-descriptor %edx 0x10)
14304     #
14305     (write _test-input-stream "fn foo {\n")
14306     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
14307     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
14308     (write _test-input-stream "  x <- copy-object x, y\n")
14309     (write _test-input-stream "}\n")
14310     # convert
14311     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14312     # registers except esp clobbered at this point
14313     # restore ed
14314     89/<- %edx 4/r32/esp
14315     (flush _test-output-buffered-file)
14316     (flush _test-error-buffered-file)
14317 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14323     # check output
14324     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
14325     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must not have any outputs"  "F - test-copy-object-with-output: error message")
14326     # check that stop(1) was called
14327     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
14328     # don't restore from ebp
14329     81 0/subop/add %esp 8/imm32
14330     # . epilogue
14331     5d/pop-to-ebp
14332     c3/return
14333 
14334 test-copy-object-deref-address:
14335     # . prologue
14336     55/push-ebp
14337     89/<- %ebp 4/r32/esp
14338     # setup
14339     (clear-stream _test-input-stream)
14340     (clear-stream $_test-input-buffered-file->buffer)
14341     (clear-stream _test-output-stream)
14342     (clear-stream $_test-output-buffered-file->buffer)
14343     #
14344     (write _test-input-stream "fn foo {\n")
14345     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
14346     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
14347     (write _test-input-stream "  copy-object *y, x\n")
14348     (write _test-input-stream "}\n")
14349     # convert
14350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14351     (flush _test-output-buffered-file)
14352     # no errors
14353     # . epilogue
14354     5d/pop-to-ebp
14355     c3/return
14356 
14357 test-copy-object-non-addr:
14358     # . prologue
14359     55/push-ebp
14360     89/<- %ebp 4/r32/esp
14361     # setup
14362     (clear-stream _test-input-stream)
14363     (clear-stream $_test-input-buffered-file->buffer)
14364     (clear-stream _test-output-stream)
14365     (clear-stream $_test-output-buffered-file->buffer)
14366     (clear-stream _test-error-stream)
14367     (clear-stream $_test-error-buffered-file->buffer)
14368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14369     68/push 0/imm32
14370     68/push 0/imm32
14371     89/<- %edx 4/r32/esp
14372     (tailor-exit-descriptor %edx 0x10)
14373     #
14374     (write _test-input-stream "fn foo {\n")
14375     (write _test-input-stream "  var x: int\n")
14376     (write _test-input-stream "  var y: int\n")
14377     (write _test-input-stream "  copy-object y, x\n")
14378     (write _test-input-stream "}\n")
14379     # convert
14380     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14381     # registers except esp clobbered at this point
14382     # restore ed
14383     89/<- %edx 4/r32/esp
14384     (flush _test-output-buffered-file)
14385     (flush _test-error-buffered-file)
14386 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14392     # check output
14393     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
14394     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-addr: error message")
14395     # check that stop(1) was called
14396     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
14397     # don't restore from ebp
14398     81 0/subop/add %esp 8/imm32
14399     # . epilogue
14400     5d/pop-to-ebp
14401     c3/return
14402 
14403 test-copy-object-non-equal:
14404     # . prologue
14405     55/push-ebp
14406     89/<- %ebp 4/r32/esp
14407     # setup
14408     (clear-stream _test-input-stream)
14409     (clear-stream $_test-input-buffered-file->buffer)
14410     (clear-stream _test-output-stream)
14411     (clear-stream $_test-output-buffered-file->buffer)
14412     (clear-stream _test-error-stream)
14413     (clear-stream $_test-error-buffered-file->buffer)
14414     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14415     68/push 0/imm32
14416     68/push 0/imm32
14417     89/<- %edx 4/r32/esp
14418     (tailor-exit-descriptor %edx 0x10)
14419     #
14420     (write _test-input-stream "fn foo {\n")
14421     (write _test-input-stream "  var x: (addr int)\n")
14422     (write _test-input-stream "  var y: (addr boolean)\n")
14423     (write _test-input-stream "  copy-object y, x\n")
14424     (write _test-input-stream "}\n")
14425     # convert
14426     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14427     # registers except esp clobbered at this point
14428     # restore ed
14429     89/<- %edx 4/r32/esp
14430     (flush _test-output-buffered-file)
14431     (flush _test-error-buffered-file)
14432 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14438     # check output
14439     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
14440     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-equal: error message")
14441     # check that stop(1) was called
14442     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
14443     # don't restore from ebp
14444     81 0/subop/add %esp 8/imm32
14445     # . epilogue
14446     5d/pop-to-ebp
14447     c3/return
14448 
14449 test-allocate-with-no-inout:
14450     # . prologue
14451     55/push-ebp
14452     89/<- %ebp 4/r32/esp
14453     # setup
14454     (clear-stream _test-input-stream)
14455     (clear-stream $_test-input-buffered-file->buffer)
14456     (clear-stream _test-output-stream)
14457     (clear-stream $_test-output-buffered-file->buffer)
14458     (clear-stream _test-error-stream)
14459     (clear-stream $_test-error-buffered-file->buffer)
14460     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14461     68/push 0/imm32
14462     68/push 0/imm32
14463     89/<- %edx 4/r32/esp
14464     (tailor-exit-descriptor %edx 0x10)
14465     #
14466     (write _test-input-stream "fn foo {\n")
14467     (write _test-input-stream "  allocate\n")
14468     (write _test-input-stream "}\n")
14469     # convert
14470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14471     # registers except esp clobbered at this point
14472     # restore ed
14473     89/<- %edx 4/r32/esp
14474     (flush _test-output-buffered-file)
14475     (flush _test-error-buffered-file)
14476 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14482     # check output
14483     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
14484     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
14485     # check that stop(1) was called
14486     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
14487     # don't restore from ebp
14488     81 0/subop/add %esp 8/imm32
14489     # . epilogue
14490     5d/pop-to-ebp
14491     c3/return
14492 
14493 test-allocate-with-too-many-inouts:
14494     # . prologue
14495     55/push-ebp
14496     89/<- %ebp 4/r32/esp
14497     # setup
14498     (clear-stream _test-input-stream)
14499     (clear-stream $_test-input-buffered-file->buffer)
14500     (clear-stream _test-output-stream)
14501     (clear-stream $_test-output-buffered-file->buffer)
14502     (clear-stream _test-error-stream)
14503     (clear-stream $_test-error-buffered-file->buffer)
14504     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14505     68/push 0/imm32
14506     68/push 0/imm32
14507     89/<- %edx 4/r32/esp
14508     (tailor-exit-descriptor %edx 0x10)
14509     #
14510     (write _test-input-stream "fn foo {\n")
14511     (write _test-input-stream "  var x: (addr handle int)\n")
14512     (write _test-input-stream "  allocate x, 0\n")
14513     (write _test-input-stream "}\n")
14514     # convert
14515     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14516     # registers except esp clobbered at this point
14517     # restore ed
14518     89/<- %edx 4/r32/esp
14519     (flush _test-output-buffered-file)
14520     (flush _test-error-buffered-file)
14521 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14527     # check output
14528     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
14529     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-too-many-inouts: error message")
14530     # check that stop(1) was called
14531     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
14532     # don't restore from ebp
14533     81 0/subop/add %esp 8/imm32
14534     # . epilogue
14535     5d/pop-to-ebp
14536     c3/return
14537 
14538 test-allocate-with-output:
14539     # . prologue
14540     55/push-ebp
14541     89/<- %ebp 4/r32/esp
14542     # setup
14543     (clear-stream _test-input-stream)
14544     (clear-stream $_test-input-buffered-file->buffer)
14545     (clear-stream _test-output-stream)
14546     (clear-stream $_test-output-buffered-file->buffer)
14547     (clear-stream _test-error-stream)
14548     (clear-stream $_test-error-buffered-file->buffer)
14549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14550     68/push 0/imm32
14551     68/push 0/imm32
14552     89/<- %edx 4/r32/esp
14553     (tailor-exit-descriptor %edx 0x10)
14554     #
14555     (write _test-input-stream "fn foo {\n")
14556     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14557     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14558     (write _test-input-stream "  x <- allocate y\n")
14559     (write _test-input-stream "}\n")
14560     # convert
14561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14562     # registers except esp clobbered at this point
14563     # restore ed
14564     89/<- %edx 4/r32/esp
14565     (flush _test-output-buffered-file)
14566     (flush _test-error-buffered-file)
14567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14573     # check output
14574     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
14575     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
14576     # check that stop(1) was called
14577     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
14578     # don't restore from ebp
14579     81 0/subop/add %esp 8/imm32
14580     # . epilogue
14581     5d/pop-to-ebp
14582     c3/return
14583 
14584 test-allocate-non-addr:
14585     # . prologue
14586     55/push-ebp
14587     89/<- %ebp 4/r32/esp
14588     # setup
14589     (clear-stream _test-input-stream)
14590     (clear-stream $_test-input-buffered-file->buffer)
14591     (clear-stream _test-output-stream)
14592     (clear-stream $_test-output-buffered-file->buffer)
14593     (clear-stream _test-error-stream)
14594     (clear-stream $_test-error-buffered-file->buffer)
14595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14596     68/push 0/imm32
14597     68/push 0/imm32
14598     89/<- %edx 4/r32/esp
14599     (tailor-exit-descriptor %edx 0x10)
14600     #
14601     (write _test-input-stream "fn foo {\n")
14602     (write _test-input-stream "  var y: (handle int)\n")
14603     (write _test-input-stream "  allocate y\n")
14604     (write _test-input-stream "}\n")
14605     # convert
14606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14607     # registers except esp clobbered at this point
14608     # restore ed
14609     89/<- %edx 4/r32/esp
14610     (flush _test-output-buffered-file)
14611     (flush _test-error-buffered-file)
14612 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14618     # check output
14619     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
14620     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
14621     # check that stop(1) was called
14622     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
14623     # don't restore from ebp
14624     81 0/subop/add %esp 8/imm32
14625     # . epilogue
14626     5d/pop-to-ebp
14627     c3/return
14628 
14629 test-allocate-non-addr-handle:
14630     # . prologue
14631     55/push-ebp
14632     89/<- %ebp 4/r32/esp
14633     # setup
14634     (clear-stream _test-input-stream)
14635     (clear-stream $_test-input-buffered-file->buffer)
14636     (clear-stream _test-output-stream)
14637     (clear-stream $_test-output-buffered-file->buffer)
14638     (clear-stream _test-error-stream)
14639     (clear-stream $_test-error-buffered-file->buffer)
14640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14641     68/push 0/imm32
14642     68/push 0/imm32
14643     89/<- %edx 4/r32/esp
14644     (tailor-exit-descriptor %edx 0x10)
14645     #
14646     (write _test-input-stream "fn foo {\n")
14647     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14648     (write _test-input-stream "  allocate y\n")
14649     (write _test-input-stream "}\n")
14650     # convert
14651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14652     # registers except esp clobbered at this point
14653     # restore ed
14654     89/<- %edx 4/r32/esp
14655     (flush _test-output-buffered-file)
14656     (flush _test-error-buffered-file)
14657 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14663     # check output
14664     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
14665     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr-handle: error message")
14666     # check that stop(1) was called
14667     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
14668     # don't restore from ebp
14669     81 0/subop/add %esp 8/imm32
14670     # . epilogue
14671     5d/pop-to-ebp
14672     c3/return
14673 
14674 test-allocate-deref-address:
14675     # . prologue
14676     55/push-ebp
14677     89/<- %ebp 4/r32/esp
14678     # setup
14679     (clear-stream _test-input-stream)
14680     (clear-stream $_test-input-buffered-file->buffer)
14681     (clear-stream _test-output-stream)
14682     (clear-stream $_test-output-buffered-file->buffer)
14683     #
14684     (write _test-input-stream "fn foo {\n")
14685     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
14686     (write _test-input-stream "  allocate *y\n")
14687     (write _test-input-stream "}\n")
14688     # convert
14689     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14690     (flush _test-output-buffered-file)
14691     # no errors
14692     # . epilogue
14693     5d/pop-to-ebp
14694     c3/return
14695 
14696 test-populate-with-no-inout:
14697     # . prologue
14698     55/push-ebp
14699     89/<- %ebp 4/r32/esp
14700     # setup
14701     (clear-stream _test-input-stream)
14702     (clear-stream $_test-input-buffered-file->buffer)
14703     (clear-stream _test-output-stream)
14704     (clear-stream $_test-output-buffered-file->buffer)
14705     (clear-stream _test-error-stream)
14706     (clear-stream $_test-error-buffered-file->buffer)
14707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14708     68/push 0/imm32
14709     68/push 0/imm32
14710     89/<- %edx 4/r32/esp
14711     (tailor-exit-descriptor %edx 0x10)
14712     #
14713     (write _test-input-stream "fn foo {\n")
14714     (write _test-input-stream "  populate\n")
14715     (write _test-input-stream "}\n")
14716     # convert
14717     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14718     # registers except esp clobbered at this point
14719     # restore ed
14720     89/<- %edx 4/r32/esp
14721     (flush _test-output-buffered-file)
14722     (flush _test-error-buffered-file)
14723 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14729     # check output
14730     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
14731     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
14732     # check that stop(1) was called
14733     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
14734     # don't restore from ebp
14735     81 0/subop/add %esp 8/imm32
14736     # . epilogue
14737     5d/pop-to-ebp
14738     c3/return
14739 
14740 test-populate-with-too-many-inouts:
14741     # . prologue
14742     55/push-ebp
14743     89/<- %ebp 4/r32/esp
14744     # setup
14745     (clear-stream _test-input-stream)
14746     (clear-stream $_test-input-buffered-file->buffer)
14747     (clear-stream _test-output-stream)
14748     (clear-stream $_test-output-buffered-file->buffer)
14749     (clear-stream _test-error-stream)
14750     (clear-stream $_test-error-buffered-file->buffer)
14751     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14752     68/push 0/imm32
14753     68/push 0/imm32
14754     89/<- %edx 4/r32/esp
14755     (tailor-exit-descriptor %edx 0x10)
14756     #
14757     (write _test-input-stream "fn foo {\n")
14758     (write _test-input-stream "  var x: (addr handle int)\n")
14759     (write _test-input-stream "  populate x, 3, 0\n")
14760     (write _test-input-stream "}\n")
14761     # convert
14762     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14763     # registers except esp clobbered at this point
14764     # restore ed
14765     89/<- %edx 4/r32/esp
14766     (flush _test-output-buffered-file)
14767     (flush _test-error-buffered-file)
14768 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14774     # check output
14775     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
14776     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-too-many-inouts: error message")
14777     # check that stop(1) was called
14778     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
14779     # don't restore from ebp
14780     81 0/subop/add %esp 8/imm32
14781     # . epilogue
14782     5d/pop-to-ebp
14783     c3/return
14784 
14785 test-populate-with-output:
14786     # . prologue
14787     55/push-ebp
14788     89/<- %ebp 4/r32/esp
14789     # setup
14790     (clear-stream _test-input-stream)
14791     (clear-stream $_test-input-buffered-file->buffer)
14792     (clear-stream _test-output-stream)
14793     (clear-stream $_test-output-buffered-file->buffer)
14794     (clear-stream _test-error-stream)
14795     (clear-stream $_test-error-buffered-file->buffer)
14796     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14797     68/push 0/imm32
14798     68/push 0/imm32
14799     89/<- %edx 4/r32/esp
14800     (tailor-exit-descriptor %edx 0x10)
14801     #
14802     (write _test-input-stream "fn foo {\n")
14803     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
14804     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14805     (write _test-input-stream "  x <- populate y\n")
14806     (write _test-input-stream "}\n")
14807     # convert
14808     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14809     # registers except esp clobbered at this point
14810     # restore ed
14811     89/<- %edx 4/r32/esp
14812     (flush _test-output-buffered-file)
14813     (flush _test-error-buffered-file)
14814 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14820     # check output
14821     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
14822     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
14823     # check that stop(1) was called
14824     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
14825     # don't restore from ebp
14826     81 0/subop/add %esp 8/imm32
14827     # . epilogue
14828     5d/pop-to-ebp
14829     c3/return
14830 
14831 test-populate-non-addr:
14832     # . prologue
14833     55/push-ebp
14834     89/<- %ebp 4/r32/esp
14835     # setup
14836     (clear-stream _test-input-stream)
14837     (clear-stream $_test-input-buffered-file->buffer)
14838     (clear-stream _test-output-stream)
14839     (clear-stream $_test-output-buffered-file->buffer)
14840     (clear-stream _test-error-stream)
14841     (clear-stream $_test-error-buffered-file->buffer)
14842     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14843     68/push 0/imm32
14844     68/push 0/imm32
14845     89/<- %edx 4/r32/esp
14846     (tailor-exit-descriptor %edx 0x10)
14847     #
14848     (write _test-input-stream "fn foo {\n")
14849     (write _test-input-stream "  var y: (handle int)\n")
14850     (write _test-input-stream "  populate y, 3\n")
14851     (write _test-input-stream "}\n")
14852     # convert
14853     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14854     # registers except esp clobbered at this point
14855     # restore ed
14856     89/<- %edx 4/r32/esp
14857     (flush _test-output-buffered-file)
14858     (flush _test-error-buffered-file)
14859 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14865     # check output
14866     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
14867     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
14868     # check that stop(1) was called
14869     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
14870     # don't restore from ebp
14871     81 0/subop/add %esp 8/imm32
14872     # . epilogue
14873     5d/pop-to-ebp
14874     c3/return
14875 
14876 test-populate-non-addr-handle:
14877     # . prologue
14878     55/push-ebp
14879     89/<- %ebp 4/r32/esp
14880     # setup
14881     (clear-stream _test-input-stream)
14882     (clear-stream $_test-input-buffered-file->buffer)
14883     (clear-stream _test-output-stream)
14884     (clear-stream $_test-output-buffered-file->buffer)
14885     (clear-stream _test-error-stream)
14886     (clear-stream $_test-error-buffered-file->buffer)
14887     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14888     68/push 0/imm32
14889     68/push 0/imm32
14890     89/<- %edx 4/r32/esp
14891     (tailor-exit-descriptor %edx 0x10)
14892     #
14893     (write _test-input-stream "fn foo {\n")
14894     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14895     (write _test-input-stream "  populate y, 3\n")
14896     (write _test-input-stream "}\n")
14897     # convert
14898     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14899     # registers except esp clobbered at this point
14900     # restore ed
14901     89/<- %edx 4/r32/esp
14902     (flush _test-output-buffered-file)
14903     (flush _test-error-buffered-file)
14904 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14910     # check output
14911     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
14912     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
14913     # check that stop(1) was called
14914     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
14915     # don't restore from ebp
14916     81 0/subop/add %esp 8/imm32
14917     # . epilogue
14918     5d/pop-to-ebp
14919     c3/return
14920 
14921 test-populate-non-addr-handle-array:
14922     # . prologue
14923     55/push-ebp
14924     89/<- %ebp 4/r32/esp
14925     # setup
14926     (clear-stream _test-input-stream)
14927     (clear-stream $_test-input-buffered-file->buffer)
14928     (clear-stream _test-output-stream)
14929     (clear-stream $_test-output-buffered-file->buffer)
14930     (clear-stream _test-error-stream)
14931     (clear-stream $_test-error-buffered-file->buffer)
14932     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14933     68/push 0/imm32
14934     68/push 0/imm32
14935     89/<- %edx 4/r32/esp
14936     (tailor-exit-descriptor %edx 0x10)
14937     #
14938     (write _test-input-stream "fn foo {\n")
14939     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14940     (write _test-input-stream "  populate y, 3\n")
14941     (write _test-input-stream "}\n")
14942     # convert
14943     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14944     # registers except esp clobbered at this point
14945     # restore ed
14946     89/<- %edx 4/r32/esp
14947     (flush _test-output-buffered-file)
14948     (flush _test-error-buffered-file)
14949 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
14955     # check output
14956     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
14957     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle-array: error message")
14958     # check that stop(1) was called
14959     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
14960     # don't restore from ebp
14961     81 0/subop/add %esp 8/imm32
14962     # . epilogue
14963     5d/pop-to-ebp
14964     c3/return
14965 
14966 test-populate-deref-address:
14967     # . prologue
14968     55/push-ebp
14969     89/<- %ebp 4/r32/esp
14970     # setup
14971     (clear-stream _test-input-stream)
14972     (clear-stream $_test-input-buffered-file->buffer)
14973     (clear-stream _test-output-stream)
14974     (clear-stream $_test-output-buffered-file->buffer)
14975     #
14976     (write _test-input-stream "fn foo {\n")
14977     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
14978     (write _test-input-stream "  populate *y, 3\n")
14979     (write _test-input-stream "}\n")
14980     # convert
14981     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14982     (flush _test-output-buffered-file)
14983     # no errors
14984     # . epilogue
14985     5d/pop-to-ebp
14986     c3/return
14987 
14988 test-populate-stream-with-no-inout:
14989     # . prologue
14990     55/push-ebp
14991     89/<- %ebp 4/r32/esp
14992     # setup
14993     (clear-stream _test-input-stream)
14994     (clear-stream $_test-input-buffered-file->buffer)
14995     (clear-stream _test-output-stream)
14996     (clear-stream $_test-output-buffered-file->buffer)
14997     (clear-stream _test-error-stream)
14998     (clear-stream $_test-error-buffered-file->buffer)
14999     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15000     68/push 0/imm32
15001     68/push 0/imm32
15002     89/<- %edx 4/r32/esp
15003     (tailor-exit-descriptor %edx 0x10)
15004     #
15005     (write _test-input-stream "fn foo {\n")
15006     (write _test-input-stream "  populate-stream\n")
15007     (write _test-input-stream "}\n")
15008     # convert
15009     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15010     # registers except esp clobbered at this point
15011     # restore ed
15012     89/<- %edx 4/r32/esp
15013     (flush _test-output-buffered-file)
15014     (flush _test-error-buffered-file)
15015 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15021     # check output
15022     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
15023     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
15024     # check that stop(1) was called
15025     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
15026     # don't restore from ebp
15027     81 0/subop/add %esp 8/imm32
15028     # . epilogue
15029     5d/pop-to-ebp
15030     c3/return
15031 
15032 test-populate-stream-with-too-many-inouts:
15033     # . prologue
15034     55/push-ebp
15035     89/<- %ebp 4/r32/esp
15036     # setup
15037     (clear-stream _test-input-stream)
15038     (clear-stream $_test-input-buffered-file->buffer)
15039     (clear-stream _test-output-stream)
15040     (clear-stream $_test-output-buffered-file->buffer)
15041     (clear-stream _test-error-stream)
15042     (clear-stream $_test-error-buffered-file->buffer)
15043     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15044     68/push 0/imm32
15045     68/push 0/imm32
15046     89/<- %edx 4/r32/esp
15047     (tailor-exit-descriptor %edx 0x10)
15048     #
15049     (write _test-input-stream "fn foo {\n")
15050     (write _test-input-stream "  var x: (addr handle int)\n")
15051     (write _test-input-stream "  populate-stream x, 3, 0\n")
15052     (write _test-input-stream "}\n")
15053     # convert
15054     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15055     # registers except esp clobbered at this point
15056     # restore ed
15057     89/<- %edx 4/r32/esp
15058     (flush _test-output-buffered-file)
15059     (flush _test-error-buffered-file)
15060 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15066     # check output
15067     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
15068     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-too-many-inouts: error message")
15069     # check that stop(1) was called
15070     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
15071     # don't restore from ebp
15072     81 0/subop/add %esp 8/imm32
15073     # . epilogue
15074     5d/pop-to-ebp
15075     c3/return
15076 
15077 test-populate-stream-with-output:
15078     # . prologue
15079     55/push-ebp
15080     89/<- %ebp 4/r32/esp
15081     # setup
15082     (clear-stream _test-input-stream)
15083     (clear-stream $_test-input-buffered-file->buffer)
15084     (clear-stream _test-output-stream)
15085     (clear-stream $_test-output-buffered-file->buffer)
15086     (clear-stream _test-error-stream)
15087     (clear-stream $_test-error-buffered-file->buffer)
15088     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15089     68/push 0/imm32
15090     68/push 0/imm32
15091     89/<- %edx 4/r32/esp
15092     (tailor-exit-descriptor %edx 0x10)
15093     #
15094     (write _test-input-stream "fn foo {\n")
15095     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
15096     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15097     (write _test-input-stream "  x <- populate-stream y\n")
15098     (write _test-input-stream "}\n")
15099     # convert
15100     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15101     # registers except esp clobbered at this point
15102     # restore ed
15103     89/<- %edx 4/r32/esp
15104     (flush _test-output-buffered-file)
15105     (flush _test-error-buffered-file)
15106 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15112     # check output
15113     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
15114     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must not have any outputs"  "F - test-populate-stream-with-output: error message")
15115     # check that stop(1) was called
15116     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
15117     # don't restore from ebp
15118     81 0/subop/add %esp 8/imm32
15119     # . epilogue
15120     5d/pop-to-ebp
15121     c3/return
15122 
15123 test-populate-stream-non-addr:
15124     # . prologue
15125     55/push-ebp
15126     89/<- %ebp 4/r32/esp
15127     # setup
15128     (clear-stream _test-input-stream)
15129     (clear-stream $_test-input-buffered-file->buffer)
15130     (clear-stream _test-output-stream)
15131     (clear-stream $_test-output-buffered-file->buffer)
15132     (clear-stream _test-error-stream)
15133     (clear-stream $_test-error-buffered-file->buffer)
15134     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15135     68/push 0/imm32
15136     68/push 0/imm32
15137     89/<- %edx 4/r32/esp
15138     (tailor-exit-descriptor %edx 0x10)
15139     #
15140     (write _test-input-stream "fn foo {\n")
15141     (write _test-input-stream "  var y: (handle int)\n")
15142     (write _test-input-stream "  populate-stream y, 3\n")
15143     (write _test-input-stream "}\n")
15144     # convert
15145     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15146     # registers except esp clobbered at this point
15147     # restore ed
15148     89/<- %edx 4/r32/esp
15149     (flush _test-output-buffered-file)
15150     (flush _test-error-buffered-file)
15151 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15157     # check output
15158     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
15159     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
15160     # check that stop(1) was called
15161     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
15162     # don't restore from ebp
15163     81 0/subop/add %esp 8/imm32
15164     # . epilogue
15165     5d/pop-to-ebp
15166     c3/return
15167 
15168 test-populate-stream-non-addr-handle:
15169     # . prologue
15170     55/push-ebp
15171     89/<- %ebp 4/r32/esp
15172     # setup
15173     (clear-stream _test-input-stream)
15174     (clear-stream $_test-input-buffered-file->buffer)
15175     (clear-stream _test-output-stream)
15176     (clear-stream $_test-output-buffered-file->buffer)
15177     (clear-stream _test-error-stream)
15178     (clear-stream $_test-error-buffered-file->buffer)
15179     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15180     68/push 0/imm32
15181     68/push 0/imm32
15182     89/<- %edx 4/r32/esp
15183     (tailor-exit-descriptor %edx 0x10)
15184     #
15185     (write _test-input-stream "fn foo {\n")
15186     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
15187     (write _test-input-stream "  populate-stream y, 3\n")
15188     (write _test-input-stream "}\n")
15189     # convert
15190     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15191     # registers except esp clobbered at this point
15192     # restore ed
15193     89/<- %edx 4/r32/esp
15194     (flush _test-output-buffered-file)
15195     (flush _test-error-buffered-file)
15196 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15202     # check output
15203     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
15204     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
15205     # check that stop(1) was called
15206     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
15207     # don't restore from ebp
15208     81 0/subop/add %esp 8/imm32
15209     # . epilogue
15210     5d/pop-to-ebp
15211     c3/return
15212 
15213 test-populate-stream-non-addr-handle-stream:
15214     # . prologue
15215     55/push-ebp
15216     89/<- %ebp 4/r32/esp
15217     # setup
15218     (clear-stream _test-input-stream)
15219     (clear-stream $_test-input-buffered-file->buffer)
15220     (clear-stream _test-output-stream)
15221     (clear-stream $_test-output-buffered-file->buffer)
15222     (clear-stream _test-error-stream)
15223     (clear-stream $_test-error-buffered-file->buffer)
15224     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15225     68/push 0/imm32
15226     68/push 0/imm32
15227     89/<- %edx 4/r32/esp
15228     (tailor-exit-descriptor %edx 0x10)
15229     #
15230     (write _test-input-stream "fn foo {\n")
15231     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
15232     (write _test-input-stream "  populate-stream y, 3\n")
15233     (write _test-input-stream "}\n")
15234     # convert
15235     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15236     # registers except esp clobbered at this point
15237     # restore ed
15238     89/<- %edx 4/r32/esp
15239     (flush _test-output-buffered-file)
15240     (flush _test-error-buffered-file)
15241 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15247     # check output
15248     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
15249     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle-stream: error message")
15250     # check that stop(1) was called
15251     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
15252     # don't restore from ebp
15253     81 0/subop/add %esp 8/imm32
15254     # . epilogue
15255     5d/pop-to-ebp
15256     c3/return
15257 
15258 test-populate-stream-deref-address:
15259     # . prologue
15260     55/push-ebp
15261     89/<- %ebp 4/r32/esp
15262     # setup
15263     (clear-stream _test-input-stream)
15264     (clear-stream $_test-input-buffered-file->buffer)
15265     (clear-stream _test-output-stream)
15266     (clear-stream $_test-output-buffered-file->buffer)
15267     #
15268     (write _test-input-stream "fn foo {\n")
15269     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
15270     (write _test-input-stream "  populate-stream *y, 3\n")
15271     (write _test-input-stream "}\n")
15272     # convert
15273     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15274     (flush _test-output-buffered-file)
15275     # no errors
15276     # . epilogue
15277     5d/pop-to-ebp
15278     c3/return
15279 
15280 test-convert-with-no-inout:
15281     # . prologue
15282     55/push-ebp
15283     89/<- %ebp 4/r32/esp
15284     # setup
15285     (clear-stream _test-input-stream)
15286     (clear-stream $_test-input-buffered-file->buffer)
15287     (clear-stream _test-output-stream)
15288     (clear-stream $_test-output-buffered-file->buffer)
15289     (clear-stream _test-error-stream)
15290     (clear-stream $_test-error-buffered-file->buffer)
15291     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15292     68/push 0/imm32
15293     68/push 0/imm32
15294     89/<- %edx 4/r32/esp
15295     (tailor-exit-descriptor %edx 0x10)
15296     #
15297     (write _test-input-stream "fn foo {\n")
15298     (write _test-input-stream "  var x/eax: int <- convert\n")
15299     (write _test-input-stream "}\n")
15300     # convert
15301     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15302     # registers except esp clobbered at this point
15303     # restore ed
15304     89/<- %edx 4/r32/esp
15305     (flush _test-output-buffered-file)
15306     (flush _test-error-buffered-file)
15307 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15313     # check output
15314     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
15315     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
15316     # check that stop(1) was called
15317     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
15318     # don't restore from ebp
15319     81 0/subop/add %esp 8/imm32
15320     # . epilogue
15321     5d/pop-to-ebp
15322     c3/return
15323 
15324 test-convert-with-multiple-inouts:
15325     # . prologue
15326     55/push-ebp
15327     89/<- %ebp 4/r32/esp
15328     # setup
15329     (clear-stream _test-input-stream)
15330     (clear-stream $_test-input-buffered-file->buffer)
15331     (clear-stream _test-output-stream)
15332     (clear-stream $_test-output-buffered-file->buffer)
15333     (clear-stream _test-error-stream)
15334     (clear-stream $_test-error-buffered-file->buffer)
15335     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15336     68/push 0/imm32
15337     68/push 0/imm32
15338     89/<- %edx 4/r32/esp
15339     (tailor-exit-descriptor %edx 0x10)
15340     #
15341     (write _test-input-stream "fn foo {\n")
15342     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
15343     (write _test-input-stream "}\n")
15344     # convert
15345     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15346     # registers except esp clobbered at this point
15347     # restore ed
15348     89/<- %edx 4/r32/esp
15349     (flush _test-output-buffered-file)
15350     (flush _test-error-buffered-file)
15351 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15357     # check output
15358     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
15359     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one inout"  "F - test-convert-with-multiple-inouts: error message")
15360     # check that stop(1) was called
15361     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
15362     # don't restore from ebp
15363     81 0/subop/add %esp 8/imm32
15364     # . epilogue
15365     5d/pop-to-ebp
15366     c3/return
15367 
15368 test-convert-with-no-output:
15369     # . prologue
15370     55/push-ebp
15371     89/<- %ebp 4/r32/esp
15372     # setup
15373     (clear-stream _test-input-stream)
15374     (clear-stream $_test-input-buffered-file->buffer)
15375     (clear-stream _test-output-stream)
15376     (clear-stream $_test-output-buffered-file->buffer)
15377     (clear-stream _test-error-stream)
15378     (clear-stream $_test-error-buffered-file->buffer)
15379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15380     68/push 0/imm32
15381     68/push 0/imm32
15382     89/<- %edx 4/r32/esp
15383     (tailor-exit-descriptor %edx 0x10)
15384     #
15385     (write _test-input-stream "fn foo {\n")
15386     (write _test-input-stream "  convert 0\n")
15387     (write _test-input-stream "}\n")
15388     # convert
15389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15390     # registers except esp clobbered at this point
15391     # restore ed
15392     89/<- %edx 4/r32/esp
15393     (flush _test-output-buffered-file)
15394     (flush _test-error-buffered-file)
15395 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15401     # check output
15402     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
15403     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
15404     # check that stop(1) was called
15405     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
15406     # don't restore from ebp
15407     81 0/subop/add %esp 8/imm32
15408     # . epilogue
15409     5d/pop-to-ebp
15410     c3/return
15411 
15412 test-convert-with-multiple-outputs:
15413     # . prologue
15414     55/push-ebp
15415     89/<- %ebp 4/r32/esp
15416     # setup
15417     (clear-stream _test-input-stream)
15418     (clear-stream $_test-input-buffered-file->buffer)
15419     (clear-stream _test-output-stream)
15420     (clear-stream $_test-output-buffered-file->buffer)
15421     (clear-stream _test-error-stream)
15422     (clear-stream $_test-error-buffered-file->buffer)
15423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15424     68/push 0/imm32
15425     68/push 0/imm32
15426     89/<- %edx 4/r32/esp
15427     (tailor-exit-descriptor %edx 0x10)
15428     #
15429     (write _test-input-stream "fn foo {\n")
15430     (write _test-input-stream "  var x/eax: int <- copy 0\n")
15431     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
15432     (write _test-input-stream "  x, y <- convert 0\n")
15433     (write _test-input-stream "}\n")
15434     # convert
15435     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15436     # registers except esp clobbered at this point
15437     # restore ed
15438     89/<- %edx 4/r32/esp
15439     (flush _test-output-buffered-file)
15440     (flush _test-error-buffered-file)
15441 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15447     # check output
15448     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
15449     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one output"  "F - test-convert-with-multiple-outputs: error message")
15450     # check that stop(1) was called
15451     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
15452     # don't restore from ebp
15453     81 0/subop/add %esp 8/imm32
15454     # . epilogue
15455     5d/pop-to-ebp
15456     c3/return
15457 
15458 test-convert-deref-address:
15459     # . prologue
15460     55/push-ebp
15461     89/<- %ebp 4/r32/esp
15462     # setup
15463     (clear-stream _test-input-stream)
15464     (clear-stream $_test-input-buffered-file->buffer)
15465     (clear-stream _test-output-stream)
15466     (clear-stream $_test-output-buffered-file->buffer)
15467     #
15468     (write _test-input-stream "fn foo {\n")
15469     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
15470     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
15471     (write _test-input-stream "}\n")
15472     # convert
15473     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
15474     (flush _test-output-buffered-file)
15475     # no errors
15476     # . epilogue
15477     5d/pop-to-ebp
15478     c3/return
15479 
15480 test-convert-to-non-register:
15481     # . prologue
15482     55/push-ebp
15483     89/<- %ebp 4/r32/esp
15484     # setup
15485     (clear-stream _test-input-stream)
15486     (clear-stream $_test-input-buffered-file->buffer)
15487     (clear-stream _test-output-stream)
15488     (clear-stream $_test-output-buffered-file->buffer)
15489     (clear-stream _test-error-stream)
15490     (clear-stream $_test-error-buffered-file->buffer)
15491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15492     68/push 0/imm32
15493     68/push 0/imm32
15494     89/<- %edx 4/r32/esp
15495     (tailor-exit-descriptor %edx 0x10)
15496     #
15497     (write _test-input-stream "fn foo {\n")
15498     (write _test-input-stream "  var x: float\n")
15499     (write _test-input-stream "  var y: int\n")
15500     (write _test-input-stream "  x <- convert y\n")
15501     (write _test-input-stream "}\n")
15502     # convert
15503     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15504     # registers except esp clobbered at this point
15505     # restore ed
15506     89/<- %edx 4/r32/esp
15507     (flush _test-output-buffered-file)
15508     (flush _test-error-buffered-file)
15509 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15515     # check output
15516     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
15517     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'x' not in a register"  "F - test-convert-to-non-register: error message")
15518     # check that stop(1) was called
15519     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
15520     # don't restore from ebp
15521     81 0/subop/add %esp 8/imm32
15522     # . epilogue
15523     5d/pop-to-ebp
15524     c3/return
15525 
15526 test-convert-invalid-inout-type:
15527     # . prologue
15528     55/push-ebp
15529     89/<- %ebp 4/r32/esp
15530     # setup
15531     (clear-stream _test-input-stream)
15532     (clear-stream $_test-input-buffered-file->buffer)
15533     (clear-stream _test-output-stream)
15534     (clear-stream $_test-output-buffered-file->buffer)
15535     (clear-stream _test-error-stream)
15536     (clear-stream $_test-error-buffered-file->buffer)
15537     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15538     68/push 0/imm32
15539     68/push 0/imm32
15540     89/<- %edx 4/r32/esp
15541     (tailor-exit-descriptor %edx 0x10)
15542     #
15543     (write _test-input-stream "fn foo {\n")
15544     (write _test-input-stream "  var x: boolean\n")
15545     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
15546     (write _test-input-stream "}\n")
15547     # convert
15548     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15549     # registers except esp clobbered at this point
15550     # restore ed
15551     89/<- %edx 4/r32/esp
15552     (flush _test-output-buffered-file)
15553     (flush _test-error-buffered-file)
15554 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15560     # check output
15561     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
15562     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: inout 'x' must be an int or float"  "F - test-convert-invalid-inout-type: error message")
15563     # check that stop(1) was called
15564     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
15565     # don't restore from ebp
15566     81 0/subop/add %esp 8/imm32
15567     # . epilogue
15568     5d/pop-to-ebp
15569     c3/return
15570 
15571 test-convert-invalid-output-type:
15572     # . prologue
15573     55/push-ebp
15574     89/<- %ebp 4/r32/esp
15575     # setup
15576     (clear-stream _test-input-stream)
15577     (clear-stream $_test-input-buffered-file->buffer)
15578     (clear-stream _test-output-stream)
15579     (clear-stream $_test-output-buffered-file->buffer)
15580     (clear-stream _test-error-stream)
15581     (clear-stream $_test-error-buffered-file->buffer)
15582     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15583     68/push 0/imm32
15584     68/push 0/imm32
15585     89/<- %edx 4/r32/esp
15586     (tailor-exit-descriptor %edx 0x10)
15587     #
15588     (write _test-input-stream "fn foo {\n")
15589     (write _test-input-stream "  var x: float\n")
15590     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
15591     (write _test-input-stream "}\n")
15592     # convert
15593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15594     # registers except esp clobbered at this point
15595     # restore ed
15596     89/<- %edx 4/r32/esp
15597     (flush _test-output-buffered-file)
15598     (flush _test-error-buffered-file)
15599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15605     # check output
15606     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
15607     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'y' must be an int or float"  "F - test-convert-invalid-output-type: error message")
15608     # check that stop(1) was called
15609     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
15610     # don't restore from ebp
15611     81 0/subop/add %esp 8/imm32
15612     # . epilogue
15613     5d/pop-to-ebp
15614     c3/return
15615 
15616 test-convert-int-to-int:
15617     # . prologue
15618     55/push-ebp
15619     89/<- %ebp 4/r32/esp
15620     # setup
15621     (clear-stream _test-input-stream)
15622     (clear-stream $_test-input-buffered-file->buffer)
15623     (clear-stream _test-output-stream)
15624     (clear-stream $_test-output-buffered-file->buffer)
15625     (clear-stream _test-error-stream)
15626     (clear-stream $_test-error-buffered-file->buffer)
15627     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15628     68/push 0/imm32
15629     68/push 0/imm32
15630     89/<- %edx 4/r32/esp
15631     (tailor-exit-descriptor %edx 0x10)
15632     #
15633     (write _test-input-stream "fn foo {\n")
15634     (write _test-input-stream "  var x: int\n")
15635     (write _test-input-stream "  var y/eax: int <- convert x\n")
15636     (write _test-input-stream "}\n")
15637     # convert
15638     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15639     # registers except esp clobbered at this point
15640     # restore ed
15641     89/<- %edx 4/r32/esp
15642     (flush _test-output-buffered-file)
15643     (flush _test-error-buffered-file)
15644 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15650     # check output
15651     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
15652     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert int to int"  "F - test-convert-int-to-int: error message")
15653     # check that stop(1) was called
15654     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
15655     # don't restore from ebp
15656     81 0/subop/add %esp 8/imm32
15657     # . epilogue
15658     5d/pop-to-ebp
15659     c3/return
15660 
15661 test-convert-float-to-float:
15662     # . prologue
15663     55/push-ebp
15664     89/<- %ebp 4/r32/esp
15665     # setup
15666     (clear-stream _test-input-stream)
15667     (clear-stream $_test-input-buffered-file->buffer)
15668     (clear-stream _test-output-stream)
15669     (clear-stream $_test-output-buffered-file->buffer)
15670     (clear-stream _test-error-stream)
15671     (clear-stream $_test-error-buffered-file->buffer)
15672     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
15673     68/push 0/imm32
15674     68/push 0/imm32
15675     89/<- %edx 4/r32/esp
15676     (tailor-exit-descriptor %edx 0x10)
15677     #
15678     (write _test-input-stream "fn foo {\n")
15679     (write _test-input-stream "  var x: float\n")
15680     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
15681     (write _test-input-stream "}\n")
15682     # convert
15683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
15684     # registers except esp clobbered at this point
15685     # restore ed
15686     89/<- %edx 4/r32/esp
15687     (flush _test-output-buffered-file)
15688     (flush _test-error-buffered-file)
15689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
15695     # check output
15696     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
15697     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert float to float"  "F - test-convert-float-to-float: error message")
15698     # check that stop(1) was called
15699     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
15700     # don't restore from ebp
15701     81 0/subop/add %esp 8/imm32
15702     # . epilogue
15703     5d/pop-to-ebp
15704     c3/return
15705 
15706 #######################################################
15707 # Parsing
15708 #######################################################
15709 
15710 == data
15711 
15712 # Global state added to each var record when parsing a function
15713 Next-block-index:  # (addr int)
15714     1/imm32
15715 
15716 Curr-block-depth:  # (addr int)
15717     1/imm32
15718 
15719 == code
15720 
15721 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
15722     # pseudocode
15723     #   var curr-function: (addr handle function) = Program->functions
15724     #   var curr-signature: (addr handle function) = Program->signatures
15725     #   var curr-type: (addr handle typeinfo) = Program->types
15726     #   var line: (stream byte 512)
15727     #   var word-slice: slice
15728     #   while true                                  # line loop
15729     #     clear-stream(line)
15730     #     read-line-buffered(in, line)
15731     #     if (line->write == 0) break               # end of file
15732     #     word-slice = next-mu-token(line)
15733     #     if slice-empty?(word-slice)               # end of line
15734     #       continue
15735     #     else if slice-starts-with?(word-slice, "#")  # comment
15736     #       continue                                # end of line
15737     #     else if slice-equal?(word-slice, "fn")
15738     #       var new-function: (handle function) = allocate(function)
15739     #       var vars: (stack live-var 256)
15740     #       populate-mu-function-header(line, new-function, vars)
15741     #       populate-mu-function-body(in, new-function, vars)
15742     #       assert(vars->top == 0)
15743     #       *curr-function = new-function
15744     #       curr-function = &new-function->next
15745     #     else if slice-equal?(word-slice, "sig")
15746     #       var new-function: (handle function) = allocate(function)
15747     #       populate-mu-function-signature(line, new-function)
15748     #       *curr-signature = new-function
15749     #       curr-signature = &new-function->next
15750     #     else if slice-equal?(word-slice, "type")
15751     #       word-slice = next-mu-token(line)
15752     #       type-id = pos-or-insert-slice(Type-id, word-slice)
15753     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
15754     #       assert(next-word(line) == "{")
15755     #       populate-mu-type(in, new-type)
15756     #     else
15757     #       abort()
15758     #
15759     # . prologue
15760     55/push-ebp
15761     89/<- %ebp 4/r32/esp
15762     # var curr-signature: (addr handle function) at *(ebp-4)
15763     68/push _Program-signatures/imm32
15764     # . save registers
15765     50/push-eax
15766     51/push-ecx
15767     52/push-edx
15768     53/push-ebx
15769     56/push-esi
15770     57/push-edi
15771     # var line/ecx: (stream byte 512)
15772     81 5/subop/subtract %esp 0x200/imm32
15773     68/push 0x200/imm32/size
15774     68/push 0/imm32/read
15775     68/push 0/imm32/write
15776     89/<- %ecx 4/r32/esp
15777     # var word-slice/edx: slice
15778     68/push 0/imm32/end
15779     68/push 0/imm32/start
15780     89/<- %edx 4/r32/esp
15781     # var curr-function/edi: (addr handle function)
15782     bf/copy-to-edi _Program-functions/imm32
15783     # var vars/ebx: (stack live-var 256)
15784     81 5/subop/subtract %esp 0xc00/imm32
15785     68/push 0xc00/imm32/size
15786     68/push 0/imm32/top
15787     89/<- %ebx 4/r32/esp
15788     {
15789 $parse-mu:line-loop:
15790       (clear-stream %ecx)
15791       (read-line-buffered *(ebp+8) %ecx)
15792       # if (line->write == 0) break
15793       81 7/subop/compare *ecx 0/imm32
15794       0f 84/jump-if-= break/disp32
15795 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
15801       (next-mu-token %ecx %edx)
15802       # if slice-empty?(word-slice) continue
15803       (slice-empty? %edx)  # => eax
15804       3d/compare-eax-and 0/imm32/false
15805       0f 85/jump-if-!= loop/disp32
15806       # if (*word-slice->start == "#") continue
15807       # . eax = *word-slice->start
15808       8b/-> *edx 0/r32/eax
15809       8a/copy-byte *eax 0/r32/AL
15810       25/and-eax-with 0xff/imm32
15811       # . if (eax == '#') continue
15812       3d/compare-eax-and 0x23/imm32/hash
15813       0f 84/jump-if-= loop/disp32
15814       # if (slice-equal?(word-slice, "fn")) parse a function
15815       {
15816 $parse-mu:fn:
15817         (slice-equal? %edx "fn")  # => eax
15818         3d/compare-eax-and 0/imm32/false
15819         0f 84/jump-if-= break/disp32
15820         # var new-function/esi: (handle function)
15821         68/push 0/imm32
15822         68/push 0/imm32
15823         89/<- %esi 4/r32/esp
15824         # populate-mu-function(line, in, vars, new-function)
15825         (allocate Heap *Function-size %esi)
15826         # var new-function-addr/eax: (addr function)
15827         (lookup *esi *(esi+4))  # => eax
15828         # initialize vars
15829         (clear-stack %ebx)
15830         #
15831         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
15832         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
15833         # *curr-function = new-function
15834         8b/-> *esi 0/r32/eax
15835         89/<- *edi 0/r32/eax
15836         8b/-> *(esi+4) 0/r32/eax
15837         89/<- *(edi+4) 0/r32/eax
15838         # curr-function = &new-function->next
15839         # . var tmp/eax: (addr function) = lookup(new-function)
15840         (lookup *esi *(esi+4))  # => eax
15841         # . curr-function = &tmp->next
15842         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15843         # reclaim new-function
15844         81 0/subop/add %esp 8/imm32
15845         #
15846         e9/jump $parse-mu:line-loop/disp32
15847       }
15848       # if (slice-equal?(word-slice, "sig")) parse a function signature
15849       # Function signatures are for providing types to SubX functions.
15850       {
15851 $parse-mu:sig:
15852         (slice-equal? %edx "sig")  # => eax
15853         3d/compare-eax-and 0/imm32/false
15854         0f 84/jump-if-= break/disp32
15855         # edi = curr-function
15856         57/push-edi
15857         8b/-> *(ebp-4) 7/r32/edi
15858         # var new-function/esi: (handle function)
15859         68/push 0/imm32
15860         68/push 0/imm32
15861         89/<- %esi 4/r32/esp
15862         # populate-mu-function(line, in, vars, new-function)
15863         (allocate Heap *Function-size %esi)
15864         # var new-function-addr/eax: (addr function)
15865         (lookup *esi *(esi+4))  # => eax
15866         #
15867         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
15868         # *curr-signature = new-function
15869         8b/-> *esi 0/r32/eax
15870         89/<- *edi 0/r32/eax
15871         8b/-> *(esi+4) 0/r32/eax
15872         89/<- *(edi+4) 0/r32/eax
15873         # curr-signature = &new-function->next
15874         # . var tmp/eax: (addr function) = lookup(new-function)
15875         (lookup *esi *(esi+4))  # => eax
15876         # . curr-function = &tmp->next
15877         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
15878         # reclaim new-function
15879         81 0/subop/add %esp 8/imm32
15880         # save curr-function
15881         89/<- *(ebp-4) 7/r32/edi
15882         # restore edi
15883         5f/pop-to-edi
15884         #
15885         e9/jump $parse-mu:line-loop/disp32
15886       }
15887       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
15888       {
15889 $parse-mu:type:
15890         (slice-equal? %edx "type")  # => eax
15891         3d/compare-eax-and 0/imm32
15892         0f 84/jump-if-= break/disp32
15893         (next-mu-token %ecx %edx)
15894         # var type-id/eax: int
15895         (pos-or-insert-slice Type-id %edx)  # => eax
15896         # spill
15897         51/push-ecx
15898         # var new-type/ecx: (handle typeinfo)
15899         68/push 0/imm32
15900         68/push 0/imm32
15901         89/<- %ecx 4/r32/esp
15902         (find-or-create-typeinfo %eax %ecx)
15903         #
15904         (lookup *ecx *(ecx+4))  # => eax
15905         # TODO: ensure that 'line' has nothing else but '{'
15906 #? (dump-typeinfos "=== aaa\n")
15907         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
15908 #? (dump-typeinfos "=== zzz\n")
15909         # reclaim new-type
15910         81 0/subop/add %esp 8/imm32
15911         # restore
15912         59/pop-to-ecx
15913         e9/jump $parse-mu:line-loop/disp32
15914       }
15915       # otherwise abort
15916       e9/jump $parse-mu:error1/disp32
15917     } # end line loop
15918 $parse-mu:end:
15919     # . reclaim locals
15920     81 0/subop/add %esp 0x20c/imm32  # line
15921     81 0/subop/add %esp 0xc08/imm32  # vars
15922     81 0/subop/add %esp 8/imm32
15923     # . restore registers
15924     5f/pop-to-edi
15925     5e/pop-to-esi
15926     5b/pop-to-ebx
15927     5a/pop-to-edx
15928     59/pop-to-ecx
15929     58/pop-to-eax
15930     # . reclaim local
15931     81 0/subop/add %esp 4/imm32
15932     # . epilogue
15933     89/<- %esp 5/r32/ebp
15934     5d/pop-to-ebp
15935     c3/return
15936 
15937 $parse-mu:error1:
15938     # error("unexpected top-level command: " word-slice "\n")
15939     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
15940     (write-slice-buffered *(ebp+0xc) %edx)
15941     (write-buffered *(ebp+0xc) "\n")
15942     (flush *(ebp+0xc))
15943     (stop *(ebp+0x10) 1)
15944     # never gets here
15945 
15946 $parse-mu:error2:
15947     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
15948     (write-int32-hex-buffered *(ebp+0xc) *ebx)
15949     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
15950     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
15951     (write-buffered *(ebp+0xc) "'\n")
15952     (flush *(ebp+0xc))
15953     (stop *(ebp+0x10) 1)
15954     # never gets here
15955 
15956 # scenarios considered:
15957 # ✗ fn foo  # no block
15958 # ✓ fn foo {
15959 # ✗ fn foo { {
15960 # ✗ fn foo { }
15961 # ✗ fn foo { } {
15962 # ✗ fn foo x {
15963 # ✗ fn foo x: {
15964 # ✓ fn foo x: int {
15965 # ✓ fn foo x: int {
15966 # ✓ fn foo x: int -> _/eax: int {
15967 # TODO:
15968 #   disallow outputs of type `(... addr ...)`
15969 #   disallow inputs of type `(... addr ... addr ...)`
15970 populate-mu-function-header:  # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
15971     # pseudocode:
15972     #   var word-slice: slice
15973     #   next-mu-token(first-line, word-slice)
15974     #   if slice-empty?(word-slice) abort
15975     #   assert(word-slice not in '{' '}' '->')
15976     #   out->name = slice-to-string(word-slice)
15977     #   ## inouts
15978     #   while true
15979     #     word-slice = next-mu-token(first-line)
15980     #     if slice-empty?(word-slice) abort
15981     #     if (word-slice == '{') goto done
15982     #     if (word-slice == '->') break
15983     #     assert(word-slice != '}')
15984     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15985     #     assert(v->register == null)
15986     #     # v->block-depth is implicitly 0
15987     #     out->inouts = append(v, out->inouts)
15988     #     push(vars, {v, false})
15989     #   ## outputs
15990     #   while true
15991     #     word-slice = next-mu-token(first-line)
15992     #     if slice-empty?(word-slice) abort
15993     #     if (word-slice == '{') break
15994     #     assert(word-slice not in '}' '->')
15995     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
15996     #     assert(v->register != null)
15997     #     assert(v->name == "_")
15998     #     out->outputs = append(v, out->outputs)
15999     #   done:
16000     #
16001     # . prologue
16002     55/push-ebp
16003     89/<- %ebp 4/r32/esp
16004     # . save registers
16005     50/push-eax
16006     51/push-ecx
16007     52/push-edx
16008     53/push-ebx
16009     57/push-edi
16010     # edi = out
16011     8b/-> *(ebp+0xc) 7/r32/edi
16012     # var word-slice/ecx: slice
16013     68/push 0/imm32/end
16014     68/push 0/imm32/start
16015     89/<- %ecx 4/r32/esp
16016     # var v/ebx: (handle var)
16017     68/push 0/imm32
16018     68/push 0/imm32
16019     89/<- %ebx 4/r32/esp
16020     # read function name
16021     (next-mu-token *(ebp+8) %ecx)
16022     # error checking
16023     # if slice-empty?(word-slice) abort
16024     (slice-empty? %ecx)  # => eax
16025     3d/compare-eax-and 0/imm32/false
16026     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16027     # if (word-slice == '{') abort
16028     (slice-equal? %ecx "{")   # => eax
16029     3d/compare-eax-and 0/imm32/false
16030     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16031     # if (word-slice == '->') abort
16032     (slice-equal? %ecx "->")   # => eax
16033     3d/compare-eax-and 0/imm32/false
16034     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16035     # if (word-slice == '}') abort
16036     (slice-equal? %ecx "}")   # => eax
16037     3d/compare-eax-and 0/imm32/false
16038     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16039     # if word-slice already defined, abort
16040     (function-exists? %ecx)  # => eax
16041     3d/compare-eax-and 0/imm32/false
16042     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
16043     #
16044     (slice-starts-with? %ecx "break")  # => eax
16045     3d/compare-eax-and 0/imm32/false
16046     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
16047     (slice-starts-with? %ecx "loop")  # => eax
16048     3d/compare-eax-and 0/imm32/false
16049     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
16050     (slice-equal? %ecx "lookup")  # => eax
16051     3d/compare-eax-and 0/imm32/false
16052     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
16053     # save function name
16054     (slice-to-string Heap %ecx %edi)  # Function-name
16055     # save function inouts
16056     {
16057 $populate-mu-function-header:check-for-inout:
16058       (next-mu-token *(ebp+8) %ecx)
16059       # if slice-empty?(word-slice) abort
16060       (slice-empty? %ecx)  # => eax
16061       3d/compare-eax-and 0/imm32/false
16062       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16063       # if (word-slice == '{') goto done
16064       (slice-equal? %ecx "{")   # => eax
16065       3d/compare-eax-and 0/imm32/false
16066       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
16067       # if (word-slice == '->') break
16068       (slice-equal? %ecx "->")   # => eax
16069       3d/compare-eax-and 0/imm32/false
16070       0f 85/jump-if-!= break/disp32
16071       # if (word-slice == '}') abort
16072       (slice-equal? %ecx "}")   # => eax
16073       3d/compare-eax-and 0/imm32/false
16074       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16075       # v = parse-var-with-type(word-slice, first-line)
16076       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16077       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16078       # if (v->register != null) abort
16079       # . eax: (addr var) = lookup(v)
16080       (lookup *ebx *(ebx+4))  # => eax
16081       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16082       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
16083       # if function name is not "main"
16084       #    and v->type contains an 'addr' anywhere except the start, abort
16085       {
16086         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16087         (string-equal? %eax "main")  # => eax
16088         3d/compare-eax-and 0/imm32/false
16089         75/jump-if-!= break/disp8
16090         (lookup *ebx *(ebx+4))  # => eax
16091         (addr-payload-contains-addr? %eax)  # => eax
16092         3d/compare-eax-and 0/imm32/false
16093         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
16094       }
16095       # v->block-depth is implicitly 0
16096       #
16097       # out->inouts = append(v, out->inouts)
16098       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16099       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16100       # push(vars, {v, false})
16101       (push *(ebp+0x10) *ebx)
16102       (push *(ebp+0x10) *(ebx+4))
16103       (push *(ebp+0x10) 0)  # false
16104       #
16105       e9/jump loop/disp32
16106     }
16107     # save function outputs
16108     {
16109 $populate-mu-function-header:check-for-out:
16110       (next-mu-token *(ebp+8) %ecx)
16111       # if slice-empty?(word-slice) abort
16112       (slice-empty? %ecx)  # => eax
16113       3d/compare-eax-and 0/imm32/false
16114       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16115       # if (word-slice == '{') break
16116       (slice-equal? %ecx "{")   # => eax
16117       3d/compare-eax-and 0/imm32/false
16118       0f 85/jump-if-!= break/disp32
16119       # if (word-slice == '->') abort
16120       (slice-equal? %ecx "->")   # => eax
16121       3d/compare-eax-and 0/imm32/false
16122       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16123       # if (word-slice == '}') abort
16124       (slice-equal? %ecx "}")   # => eax
16125       3d/compare-eax-and 0/imm32/false
16126       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
16127       # v = parse-var-with-type(word-slice, first-line)
16128       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16129       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
16130       # assert(var->register != null)
16131       # . eax: (addr var) = lookup(v)
16132       (lookup *ebx *(ebx+4))  # => eax
16133       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16134       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
16135       # if (var->name != "_") abort
16136       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16137       (string-equal? %eax "_")  # => eax
16138       3d/compare-eax-and 0/imm32/false
16139       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
16140       # if v->type is an addr, abort
16141       (lookup *ebx *(ebx+4))  # => eax
16142       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16143       (mu-addr-type? %eax)  # => eax
16144       3d/compare-eax-and 0/imm32/false
16145       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
16146       # out->outputs = append(v, out->outputs)
16147       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16148       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16149       #
16150       e9/jump loop/disp32
16151     }
16152 $populate-mu-function-header:done:
16153     (check-no-tokens-left *(ebp+8))
16154 $populate-mu-function-header:end:
16155     # . reclaim locals
16156     81 0/subop/add %esp 0x10/imm32
16157     # . restore registers
16158     5f/pop-to-edi
16159     5b/pop-to-ebx
16160     5a/pop-to-edx
16161     59/pop-to-ecx
16162     58/pop-to-eax
16163     # . epilogue
16164     89/<- %esp 5/r32/ebp
16165     5d/pop-to-ebp
16166     c3/return
16167 
16168 $populate-mu-function-header:error1:
16169     # error("function header not in form 'fn <name> {'")
16170     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16171     (flush *(ebp+0x14))
16172     (rewind-stream *(ebp+8))
16173     (write-stream-data *(ebp+0x14) *(ebp+8))
16174     (write-buffered *(ebp+0x14) "'\n")
16175     (flush *(ebp+0x14))
16176     (stop *(ebp+0x18) 1)
16177     # never gets here
16178 
16179 $populate-mu-function-header:error2:
16180     # error("fn " fn ": function inout '" var "' cannot be in a register")
16181     (write-buffered *(ebp+0x14) "fn ")
16182     50/push-eax
16183     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16184     (write-buffered *(ebp+0x14) %eax)
16185     58/pop-to-eax
16186     (write-buffered *(ebp+0x14) ": function inout '")
16187     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16188     (write-buffered *(ebp+0x14) %eax)
16189     (write-buffered *(ebp+0x14) "' cannot be in a register")
16190     (flush *(ebp+0x14))
16191     (stop *(ebp+0x18) 1)
16192     # never gets here
16193 
16194 $populate-mu-function-header:error3:
16195     # error("fn " fn ": function output '" var "' must be in a register")
16196     (write-buffered *(ebp+0x14) "fn ")
16197     50/push-eax
16198     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16199     (write-buffered *(ebp+0x14) %eax)
16200     58/pop-to-eax
16201     (write-buffered *(ebp+0x14) ": function output '")
16202     (lookup *ebx *(ebx+4))  # => eax
16203     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16204     (write-buffered *(ebp+0x14) %eax)
16205     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
16206     (rewind-stream *(ebp+8))
16207     (write-stream-data *(ebp+0x14) *(ebp+8))
16208     (write-buffered *(ebp+0x14) "'\n")
16209     (flush *(ebp+0x14))
16210     (stop *(ebp+0x18) 1)
16211     # never gets here
16212 
16213 $populate-mu-function-header:error4:
16214     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16215     (write-buffered *(ebp+0x14) "fn ")
16216     50/push-eax
16217     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16218     (write-buffered *(ebp+0x14) %eax)
16219     58/pop-to-eax
16220     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
16221     (lookup *ebx *(ebx+4))  # => eax
16222     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16223     (write-buffered *(ebp+0x14) %eax)
16224     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
16225     (flush *(ebp+0x14))
16226     (stop *(ebp+0x18) 1)
16227     # never gets here
16228 
16229 $populate-mu-function-header:error-duplicate:
16230     (write-buffered *(ebp+0x14) "fn ")
16231     (write-slice-buffered *(ebp+0x14) %ecx)
16232     (write-buffered *(ebp+0x14) " defined more than once\n")
16233     (flush *(ebp+0x14))
16234     (stop *(ebp+0x18) 1)
16235     # never gets here
16236 
16237 $populate-mu-function-header:error-break:
16238     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16239     (flush *(ebp+0x14))
16240     (stop *(ebp+0x18) 1)
16241     # never gets here
16242 
16243 $populate-mu-function-header:error-loop:
16244     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16245     (flush *(ebp+0x14))
16246     (stop *(ebp+0x18) 1)
16247     # never gets here
16248 
16249 $populate-mu-function-header:error-lookup:
16250     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
16251     (flush *(ebp+0x14))
16252     (stop *(ebp+0x18) 1)
16253     # never gets here
16254 
16255 $populate-mu-function-header:error-addr-output:
16256     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16257     (write-buffered *(ebp+0x14) "fn ")
16258     50/push-eax
16259     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16260     (write-buffered *(ebp+0x14) %eax)
16261     58/pop-to-eax
16262     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16263     (flush *(ebp+0x14))
16264     (stop *(ebp+0x18) 1)
16265     # never gets here
16266 
16267 $populate-mu-function-header:error-nested-addr-inout:
16268     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
16269     (write-buffered *(ebp+0x14) "fn ")
16270     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16271     (write-buffered *(ebp+0x14) %eax)
16272     (write-buffered *(ebp+0x14) ": inout '")
16273     (lookup *ebx *(ebx+4))  # => eax
16274     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16275     (write-buffered *(ebp+0x14) %eax)
16276     (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
16277     (flush *(ebp+0x14))
16278     (stop *(ebp+0x18) 1)
16279     # never gets here
16280 
16281 # scenarios considered:
16282 # ✓ fn foo
16283 # ✗ fn foo {
16284 # ✓ fn foo x
16285 # ✓ fn foo x: int
16286 # ✓ fn foo x: int -> _/eax: int
16287 # TODO:
16288 #   disallow outputs of type `(... addr ...)`
16289 #   disallow inputs of type `(... addr ... addr ...)`
16290 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16291     # pseudocode:
16292     #   var word-slice: slice
16293     #   next-mu-token(first-line, word-slice)
16294     #   assert(word-slice not in '{' '}' '->')
16295     #   out->name = slice-to-string(word-slice)
16296     #   ## inouts
16297     #   while true
16298     #     word-slice = next-mu-token(first-line)
16299     #     if slice-empty?(word-slice) break
16300     #     if (word-slice == '->') break
16301     #     assert(word-slice not in '{' '}')
16302     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16303     #     assert(v->register == null)
16304     #     # v->block-depth is implicitly 0
16305     #     out->inouts = append(v, out->inouts)
16306     #   ## outputs
16307     #   while true
16308     #     word-slice = next-mu-token(first-line)
16309     #     if slice-empty?(word-slice) break
16310     #     assert(word-slice not in '{' '}' '->')
16311     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
16312     #     assert(v->register != null)
16313     #     out->outputs = append(v, out->outputs)
16314     #
16315     # . prologue
16316     55/push-ebp
16317     89/<- %ebp 4/r32/esp
16318     # . save registers
16319     50/push-eax
16320     51/push-ecx
16321     52/push-edx
16322     53/push-ebx
16323     57/push-edi
16324     # edi = out
16325     8b/-> *(ebp+0xc) 7/r32/edi
16326     # var word-slice/ecx: slice
16327     68/push 0/imm32/end
16328     68/push 0/imm32/start
16329     89/<- %ecx 4/r32/esp
16330     # var v/ebx: (handle var)
16331     68/push 0/imm32
16332     68/push 0/imm32
16333     89/<- %ebx 4/r32/esp
16334     # read function name
16335     (next-mu-token *(ebp+8) %ecx)
16336     # error checking
16337     # if (word-slice == '{') abort
16338     (slice-equal? %ecx "{")   # => eax
16339     3d/compare-eax-and 0/imm32/false
16340     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16341     # if (word-slice == '->') abort
16342     (slice-equal? %ecx "->")   # => eax
16343     3d/compare-eax-and 0/imm32/false
16344     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16345     # if (word-slice == '}') abort
16346     (slice-equal? %ecx "}")   # => eax
16347     3d/compare-eax-and 0/imm32/false
16348     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16349     # if word-slice already defined, abort
16350     (function-exists? %ecx)  # => eax
16351     3d/compare-eax-and 0/imm32/false
16352     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
16353     #
16354     (slice-starts-with? %ecx "break")  # => eax
16355     3d/compare-eax-and 0/imm32/false
16356     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
16357     (slice-starts-with? %ecx "loop")  # => eax
16358     3d/compare-eax-and 0/imm32/false
16359     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
16360     # save function name
16361     (slice-to-string Heap %ecx %edi)  # Function-name
16362     # save function inouts
16363     {
16364 $populate-mu-function-signature:check-for-inout:
16365       (next-mu-token *(ebp+8) %ecx)
16366       (slice-empty? %ecx)  # => eax
16367       3d/compare-eax-and 0/imm32/false
16368       0f 85/jump-if-!= break/disp32
16369       # if (word-slice == '->') break
16370       (slice-equal? %ecx "->")   # => eax
16371       3d/compare-eax-and 0/imm32/false
16372       0f 85/jump-if-!= break/disp32
16373       # if (word-slice == '{') abort
16374       (slice-equal? %ecx "{")   # => eax
16375       3d/compare-eax-and 0/imm32/false
16376       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16377       # if (word-slice == '}') abort
16378       (slice-equal? %ecx "}")   # => eax
16379       3d/compare-eax-and 0/imm32/false
16380       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16381       # v = parse-var-with-type(word-slice, first-line)
16382       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16383       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16384       # if (v->register != null) abort
16385       # . eax: (addr var) = lookup(v)
16386       (lookup *ebx *(ebx+4))  # => eax
16387       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16388       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16389       # if function name is not "main"
16390       #    and v->type contains an 'addr' anywhere except the start, abort
16391       {
16392         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16393         (string-equal? %eax "main")  # => eax
16394         3d/compare-eax-and 0/imm32/false
16395         75/jump-if-!= break/disp8
16396         (lookup *ebx *(ebx+4))  # => eax
16397         (addr-payload-contains-addr? %eax)  # => eax
16398         3d/compare-eax-and 0/imm32/false
16399         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
16400       }
16401       # assert(v->register == null)
16402       # . eax: (addr var) = lookup(v)
16403       (lookup *ebx *(ebx+4))  # => eax
16404       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16405       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
16406       # v->block-depth is implicitly 0
16407       #
16408       # out->inouts = append(v, out->inouts)
16409       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
16410       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
16411       #
16412       e9/jump loop/disp32
16413     }
16414     # save function outputs
16415     {
16416 $populate-mu-function-signature:check-for-out:
16417       (next-mu-token *(ebp+8) %ecx)
16418       (slice-empty? %ecx)  # => eax
16419       3d/compare-eax-and 0/imm32/false
16420       0f 85/jump-if-!= break/disp32
16421       # if (word-slice == '{') abort
16422       (slice-equal? %ecx "{")   # => eax
16423       3d/compare-eax-and 0/imm32/false
16424       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16425       # if (word-slice == '->') abort
16426       (slice-equal? %ecx "->")   # => eax
16427       3d/compare-eax-and 0/imm32/false
16428       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16429       # if (word-slice == '}') abort
16430       (slice-equal? %ecx "}")   # => eax
16431       3d/compare-eax-and 0/imm32/false
16432       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
16433       # v = parse-var-with-type(word-slice, first-line)
16434       (lookup *edi *(edi+4))  # Function-name Function-name => eax
16435       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
16436       # assert(var->register != null)
16437       # . eax: (addr var) = lookup(v)
16438       (lookup *ebx *(ebx+4))  # => eax
16439       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16440       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
16441       # if (var->name != "_") abort
16442       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16443       (string-equal? %eax "_")  # => eax
16444       3d/compare-eax-and 0/imm32/false
16445       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
16446       # if function name is not "lookup"
16447       #    and v->type is an addr, abort
16448       {
16449         (lookup *edi *(edi+4))  # Function-name Function-name => eax
16450         (string-equal? %eax "lookup")  # => eax
16451         3d/compare-eax-and 0/imm32/false
16452         75/jump-if-!= break/disp8
16453         (lookup *ebx *(ebx+4))  # => eax
16454         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16455         (mu-addr-type? %eax)  # => eax
16456         3d/compare-eax-and 0/imm32/false
16457         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
16458       }
16459       # out->outputs = append(v, out->outputs)
16460       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
16461       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
16462       #
16463       e9/jump loop/disp32
16464     }
16465 $populate-mu-function-signature:done:
16466     (check-no-tokens-left *(ebp+8))
16467 $populate-mu-function-signature:end:
16468     # . reclaim locals
16469     81 0/subop/add %esp 0x10/imm32
16470     # . restore registers
16471     5f/pop-to-edi
16472     5b/pop-to-ebx
16473     5a/pop-to-edx
16474     59/pop-to-ecx
16475     58/pop-to-eax
16476     # . epilogue
16477     89/<- %esp 5/r32/ebp
16478     5d/pop-to-ebp
16479     c3/return
16480 
16481 $populate-mu-function-signature:error1:
16482     # error("function signature not in form 'fn <name> {'")
16483     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
16484     (flush *(ebp+0x10))
16485     (rewind-stream *(ebp+8))
16486     (write-stream-data *(ebp+0x10) *(ebp+8))
16487     (write-buffered *(ebp+0x10) "'\n")
16488     (flush *(ebp+0x10))
16489     (stop *(ebp+0x14) 1)
16490     # never gets here
16491 
16492 $populate-mu-function-signature:error2:
16493     # error("fn " fn ": function inout '" var "' cannot be in a register")
16494     (write-buffered *(ebp+0x10) "fn ")
16495     50/push-eax
16496     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16497     (write-buffered *(ebp+0x10) %eax)
16498     58/pop-to-eax
16499     (write-buffered *(ebp+0x10) ": function inout '")
16500     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16501     (write-buffered *(ebp+0x10) %eax)
16502     (write-buffered *(ebp+0x10) "' cannot be in a register")
16503     (flush *(ebp+0x10))
16504     (stop *(ebp+0x14) 1)
16505     # never gets here
16506 
16507 $populate-mu-function-signature:error3:
16508     # error("fn " fn ": function output '" var "' must be in a register")
16509     (write-buffered *(ebp+0x10) "fn ")
16510     50/push-eax
16511     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16512     (write-buffered *(ebp+0x10) %eax)
16513     58/pop-to-eax
16514     (write-buffered *(ebp+0x10) ": function output '")
16515     (lookup *ebx *(ebx+4))  # => eax
16516     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16517     (write-buffered *(ebp+0x10) %eax)
16518     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
16519     (rewind-stream *(ebp+8))
16520     (write-stream-data *(ebp+0x10) *(ebp+8))
16521     (write-buffered *(ebp+0x10) "'\n")
16522     (flush *(ebp+0x10))
16523     (stop *(ebp+0x14) 1)
16524     # never gets here
16525 
16526 $populate-mu-function-signature:error4:
16527     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
16528     (write-buffered *(ebp+0x10) "fn ")
16529     50/push-eax
16530     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16531     (write-buffered *(ebp+0x10) %eax)
16532     58/pop-to-eax
16533     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
16534     (lookup *ebx *(ebx+4))  # => eax
16535     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16536     (write-buffered *(ebp+0x10) %eax)
16537     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
16538     (flush *(ebp+0x10))
16539     (stop *(ebp+0x14) 1)
16540     # never gets here
16541 
16542 $populate-mu-function-signature:error-duplicate:
16543     (write-buffered *(ebp+0x10) "fn ")
16544     (write-slice-buffered *(ebp+0x10) %ecx)
16545     (write-buffered *(ebp+0x10) " defined more than once\n")
16546     (flush *(ebp+0x10))
16547     (stop *(ebp+0x14) 1)
16548     # never gets here
16549 
16550 $populate-mu-function-signature:error-break:
16551     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
16552     (flush *(ebp+0x10))
16553     (stop *(ebp+0x14) 1)
16554     # never gets here
16555 
16556 $populate-mu-function-signature:error-loop:
16557     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
16558     (flush *(ebp+0x10))
16559     (stop *(ebp+0x14) 1)
16560     # never gets here
16561 
16562 $populate-mu-function-signature:error-addr-output:
16563     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
16564     (write-buffered *(ebp+0x10) "fn ")
16565     50/push-eax
16566     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16567     (write-buffered *(ebp+0x10) %eax)
16568     58/pop-to-eax
16569     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
16570     (flush *(ebp+0x10))
16571     (stop *(ebp+0x14) 1)
16572     # never gets here
16573 
16574 $populate-mu-function-signature:error-nested-addr-inout:
16575     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
16576     (write-buffered *(ebp+0x10) "fn ")
16577     (lookup *edi *(edi+4))  # Function-name Function-name => eax
16578     (write-buffered *(ebp+0x10) %eax)
16579     (write-buffered *(ebp+0x10) ": inout '")
16580     (lookup *ebx *(ebx+4))  # => eax
16581     (lookup *eax *(eax+4))  # Var-name Var-name => eax
16582     (write-buffered *(ebp+0x10) %eax)
16583     (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
16584     (flush *(ebp+0x10))
16585     (stop *(ebp+0x14) 1)
16586     # never gets here
16587 
16588 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
16589     # . prologue
16590     55/push-ebp
16591     89/<- %ebp 4/r32/esp
16592     # var t/eax: (addr type-tree) = v->type
16593     8b/-> *(ebp+8) 0/r32/eax
16594     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
16595     # if t->right contains addr, return true
16596     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16597     (type-tree-contains? %eax 2)  # addr => eax
16598     # we don't have to look at t->left as long as it's guaranteed to be an atom
16599 $addr-payload-contains-addr?:end:
16600     # . epilogue
16601     89/<- %esp 5/r32/ebp
16602     5d/pop-to-ebp
16603     c3/return
16604 
16605 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
16606     # . prologue
16607     55/push-ebp
16608     89/<- %ebp 4/r32/esp
16609     # . save registers
16610     51/push-ecx
16611     # if t is null, return false
16612     8b/-> *(ebp+8) 0/r32/eax
16613     3d/compare-eax-and 0/imm32
16614     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
16615     # if t is an atom, return (t->value == n)
16616     81 7/subop/compare *eax 0/imm32/false
16617     {
16618       74/jump-if-= break/disp8
16619       8b/-> *(ebp+0xc) 1/r32/ecx
16620       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
16621       0f 94/set-if-= %al
16622       25/and-eax-with 0xff/imm32
16623       eb/jump $type-tree-contains?:end/disp8
16624     }
16625     # if t->left contains n, return true
16626     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16627     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16628     3d/compare-eax-and 0/imm32/false
16629     75/jump-if-!= $type-tree-contains?:end/disp8
16630     # otherwise return whether t->right contains n
16631     8b/-> *(ebp+8) 0/r32/eax
16632     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
16633     (type-tree-contains? %eax *(ebp+0xc))  # => eax
16634 $type-tree-contains?:end:
16635     # . restore registers
16636     59/pop-to-ecx
16637     # . epilogue
16638     89/<- %esp 5/r32/ebp
16639     5d/pop-to-ebp
16640     c3/return
16641 
16642 function-exists?:  # s: (addr slice) -> result/eax: boolean
16643     # . prologue
16644     55/push-ebp
16645     89/<- %ebp 4/r32/esp
16646     # . save registers
16647     51/push-ecx
16648     # var curr/ecx: (addr function) = functions
16649     (lookup *_Program-functions *_Program-functions->payload)  # => eax
16650     89/<- %ecx 0/r32/eax
16651     {
16652       # if (curr == null) break
16653       81 7/subop/compare %ecx 0/imm32
16654       74/jump-if-= break/disp8
16655       # if (curr->name == s) return true
16656       {
16657         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16658         (slice-equal? *(ebp+8) %eax)  # => eax
16659         3d/compare-eax-and 0/imm32/false
16660         74/jump-if-= break/disp8
16661         b8/copy-to-eax 1/imm32/true
16662         e9/jump $function-exists?:end/disp32
16663       }
16664       # curr = curr->next
16665       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16666       89/<- %ecx 0/r32/eax
16667       #
16668       eb/jump loop/disp8
16669     }
16670     # var curr/ecx: (addr function) = signatures
16671     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
16672     89/<- %ecx 0/r32/eax
16673     {
16674       # if (curr == null) break
16675       81 7/subop/compare %ecx 0/imm32
16676       74/jump-if-= break/disp8
16677       # if (curr->name == s) return true
16678       {
16679         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16680         (slice-equal? *(ebp+8) %eax)  # => eax
16681         3d/compare-eax-and 0/imm32/false
16682         74/jump-if-= break/disp8
16683         b8/copy-to-eax 1/imm32/true
16684         eb/jump $function-exists?:end/disp8
16685       }
16686       # curr = curr->next
16687       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
16688       89/<- %ecx 0/r32/eax
16689       #
16690       eb/jump loop/disp8
16691     }
16692     # return false
16693     b8/copy-to-eax 0/imm32/false
16694 $function-exists?:end:
16695     # . restore registers
16696     59/pop-to-ecx
16697     # . epilogue
16698     89/<- %esp 5/r32/ebp
16699     5d/pop-to-ebp
16700     c3/return
16701 
16702 test-function-header-with-arg:
16703     # . prologue
16704     55/push-ebp
16705     89/<- %ebp 4/r32/esp
16706     # setup
16707     8b/-> *Primitive-type-ids 0/r32/eax
16708     89/<- *Type-id 0/r32/eax  # stream-write
16709     c7 0/subop/copy *_Program-functions 0/imm32
16710     c7 0/subop/copy *_Program-functions->payload 0/imm32
16711     c7 0/subop/copy *_Program-types 0/imm32
16712     c7 0/subop/copy *_Program-types->payload 0/imm32
16713     c7 0/subop/copy *_Program-signatures 0/imm32
16714     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16715     (clear-stream _test-input-stream)
16716     (write _test-input-stream "foo n: int {\n")
16717     # var result/ecx: function
16718     2b/subtract *Function-size 4/r32/esp
16719     89/<- %ecx 4/r32/esp
16720     (zero-out %ecx *Function-size)
16721     # var vars/ebx: (stack live-var 16)
16722     81 5/subop/subtract %esp 0xc0/imm32
16723     68/push 0xc0/imm32/size
16724     68/push 0/imm32/top
16725     89/<- %ebx 4/r32/esp
16726     # convert
16727     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16728     # check result->name
16729     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16730     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
16731     # var v/edx: (addr var) = result->inouts->value
16732     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16733     (lookup *eax *(eax+4))  # List-value List-value => eax
16734     89/<- %edx 0/r32/eax
16735     # check v->name
16736     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16737     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
16738     # check v->type
16739     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16740     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
16741     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
16742     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
16743     # . epilogue
16744     89/<- %esp 5/r32/ebp
16745     5d/pop-to-ebp
16746     c3/return
16747 
16748 test-function-header-with-multiple-args:
16749     # . prologue
16750     55/push-ebp
16751     89/<- %ebp 4/r32/esp
16752     # setup
16753     8b/-> *Primitive-type-ids 0/r32/eax
16754     89/<- *Type-id 0/r32/eax  # stream-write
16755     c7 0/subop/copy *_Program-functions 0/imm32
16756     c7 0/subop/copy *_Program-functions->payload 0/imm32
16757     c7 0/subop/copy *_Program-types 0/imm32
16758     c7 0/subop/copy *_Program-types->payload 0/imm32
16759     c7 0/subop/copy *_Program-signatures 0/imm32
16760     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16761     (clear-stream _test-input-stream)
16762     (write _test-input-stream "foo a: int, b: int c: int {\n")
16763     # result/ecx: function
16764     2b/subtract *Function-size 4/r32/esp
16765     89/<- %ecx 4/r32/esp
16766     (zero-out %ecx *Function-size)
16767     # var vars/ebx: (stack live-var 16)
16768     81 5/subop/subtract %esp 0xc0/imm32
16769     68/push 0xc0/imm32/size
16770     68/push 0/imm32/top
16771     89/<- %ebx 4/r32/esp
16772     # convert
16773     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16774     # check result->name
16775     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16776     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
16777     # var inouts/edx: (addr list var) = lookup(result->inouts)
16778     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16779     89/<- %edx 0/r32/eax
16780 $test-function-header-with-multiple-args:inout0:
16781     # var v/ebx: (addr var) = lookup(inouts->value)
16782     (lookup *edx *(edx+4))  # List-value List-value => eax
16783     89/<- %ebx 0/r32/eax
16784     # check v->name
16785     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16786     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
16787     # check v->type
16788     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16789     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
16790     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
16791     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
16792 $test-function-header-with-multiple-args:inout1:
16793     # inouts = lookup(inouts->next)
16794     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16795     89/<- %edx 0/r32/eax
16796     # v = lookup(inouts->value)
16797     (lookup *edx *(edx+4))  # List-value List-value => eax
16798     89/<- %ebx 0/r32/eax
16799     # check v->name
16800     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16801     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
16802     # check v->type
16803     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16804     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
16805     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
16806     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
16807 $test-function-header-with-multiple-args:inout2:
16808     # inouts = lookup(inouts->next)
16809     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16810     89/<- %edx 0/r32/eax
16811     # v = lookup(inouts->value)
16812     (lookup *edx *(edx+4))  # List-value List-value => eax
16813     89/<- %ebx 0/r32/eax
16814     # check v->name
16815     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16816     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
16817     # check v->type
16818     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16819     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
16820     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
16821     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
16822     # . epilogue
16823     89/<- %esp 5/r32/ebp
16824     5d/pop-to-ebp
16825     c3/return
16826 
16827 test-function-header-with-multiple-args-and-outputs:
16828     # . prologue
16829     55/push-ebp
16830     89/<- %ebp 4/r32/esp
16831     # setup
16832     8b/-> *Primitive-type-ids 0/r32/eax
16833     89/<- *Type-id 0/r32/eax  # stream-write
16834     c7 0/subop/copy *_Program-functions 0/imm32
16835     c7 0/subop/copy *_Program-functions->payload 0/imm32
16836     c7 0/subop/copy *_Program-types 0/imm32
16837     c7 0/subop/copy *_Program-types->payload 0/imm32
16838     c7 0/subop/copy *_Program-signatures 0/imm32
16839     c7 0/subop/copy *_Program-signatures->payload 0/imm32
16840     (clear-stream _test-input-stream)
16841     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
16842     # result/ecx: function
16843     2b/subtract *Function-size 4/r32/esp
16844     89/<- %ecx 4/r32/esp
16845     (zero-out %ecx *Function-size)
16846     # var vars/ebx: (stack live-var 16)
16847     81 5/subop/subtract %esp 0xc0/imm32
16848     68/push 0xc0/imm32/size
16849     68/push 0/imm32/top
16850     89/<- %ebx 4/r32/esp
16851     # convert
16852     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
16853     # check result->name
16854     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
16855     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
16856     # var inouts/edx: (addr list var) = lookup(result->inouts)
16857     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
16858     89/<- %edx 0/r32/eax
16859 $test-function-header-with-multiple-args-and-outputs:inout0:
16860     # var v/ebx: (addr var) = lookup(inouts->value)
16861     (lookup *edx *(edx+4))  # List-value List-value => eax
16862     89/<- %ebx 0/r32/eax
16863     # check v->name
16864     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16865     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
16866     # check v->type
16867     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16868     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
16869     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
16870     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
16871 $test-function-header-with-multiple-args-and-outputs:inout1:
16872     # inouts = lookup(inouts->next)
16873     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16874     89/<- %edx 0/r32/eax
16875     # v = lookup(inouts->value)
16876     (lookup *edx *(edx+4))  # List-value List-value => eax
16877     89/<- %ebx 0/r32/eax
16878     # check v->name
16879     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16880     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
16881     # check v->type
16882     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16883     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
16884     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
16885     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
16886 $test-function-header-with-multiple-args-and-outputs:inout2:
16887     # inouts = lookup(inouts->next)
16888     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16889     89/<- %edx 0/r32/eax
16890     # v = lookup(inouts->value)
16891     (lookup *edx *(edx+4))  # List-value List-value => eax
16892     89/<- %ebx 0/r32/eax
16893     # check v->name
16894     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16895     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
16896     # check v->type
16897     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16898     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
16899     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
16900     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
16901 $test-function-header-with-multiple-args-and-outputs:out0:
16902     # var outputs/edx: (addr list var) = lookup(result->outputs)
16903     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16904     89/<- %edx 0/r32/eax
16905     # v = lookup(outputs->value)
16906     (lookup *edx *(edx+4))  # List-value List-value => eax
16907     89/<- %ebx 0/r32/eax
16908     # check v->name
16909     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16910     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
16911     # check v->register
16912     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16913     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
16914     # check v->type
16915     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16916     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
16917     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
16918     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
16919 $test-function-header-with-multiple-args-and-outputs:out1:
16920     # outputs = lookup(outputs->next)
16921     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
16922     89/<- %edx 0/r32/eax
16923     # v = lookup(inouts->value)
16924     (lookup *edx *(edx+4))  # List-value List-value => eax
16925     89/<- %ebx 0/r32/eax
16926     # check v->name
16927     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16928     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
16929     # check v->register
16930     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16931     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
16932     # check v->type
16933     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
16934     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
16935     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
16936     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
16937     # . epilogue
16938     89/<- %esp 5/r32/ebp
16939     5d/pop-to-ebp
16940     c3/return
16941 
16942 # format for variables with types
16943 #   x: int
16944 #   x: int,
16945 #   x/eax: int
16946 #   x/eax: int,
16947 # ignores at most one trailing comma
16948 # does not support other, non-register metadata
16949 # WARNING: modifies name
16950 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)
16951     # pseudocode:
16952     #   var s: slice
16953     #   if (!slice-ends-with(name, ":"))
16954     #     abort
16955     #   --name->end to skip ':'
16956     #   next-token-from-slice(name->start, name->end, '/', s)
16957     #   new-var-from-slice(s, out)
16958     #   ## register
16959     #   next-token-from-slice(s->end, name->end, '/', s)
16960     #   if (!slice-empty?(s))
16961     #     out->register = slice-to-string(s)
16962     #   ## type
16963     #   var type: (handle type-tree) = parse-type(first-line)
16964     #   out->type = type
16965     #
16966     # . prologue
16967     55/push-ebp
16968     89/<- %ebp 4/r32/esp
16969     # . save registers
16970     50/push-eax
16971     51/push-ecx
16972     52/push-edx
16973     53/push-ebx
16974     56/push-esi
16975     57/push-edi
16976     # esi = name
16977     8b/-> *(ebp+8) 6/r32/esi
16978     # if (!slice-ends-with?(name, ":")) abort
16979     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
16980     49/decrement-ecx
16981     8a/copy-byte *ecx 1/r32/CL
16982     81 4/subop/and %ecx 0xff/imm32
16983     81 7/subop/compare %ecx 0x3a/imm32/colon
16984     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
16985     # --name->end to skip ':'
16986     ff 1/subop/decrement *(esi+4)
16987     # var s/ecx: slice
16988     68/push 0/imm32/end
16989     68/push 0/imm32/start
16990     89/<- %ecx 4/r32/esp
16991 $parse-var-with-type:parse-name:
16992     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
16993 $parse-var-with-type:create-var:
16994     # new-var-from-slice(s, out)
16995     (new-var-from-slice Heap %ecx *(ebp+0x10))
16996     # save out->register
16997 $parse-var-with-type:save-register:
16998     # . var out-addr/edi: (addr var) = lookup(*out)
16999     8b/-> *(ebp+0x10) 7/r32/edi
17000     (lookup *edi *(edi+4))  # => eax
17001     89/<- %edi 0/r32/eax
17002     # . s = next-token(...)
17003     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
17004     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
17005     {
17006 $parse-var-with-type:write-register:
17007       (slice-empty? %ecx)  # => eax
17008       3d/compare-eax-and 0/imm32/false
17009       75/jump-if-!= break/disp8
17010       # out->register = slice-to-string(s)
17011       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
17012       (slice-to-string Heap %ecx %eax)
17013     }
17014 $parse-var-with-type:save-type:
17015     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
17016     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
17017 $parse-var-with-type:check-register:
17018     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
17019     3d/compare-eax-and 0/imm32
17020     74/jump-if-= $parse-var-with-type:end/disp8
17021     (float-register? %eax)  # => eax
17022     {
17023       3d/compare-eax-and 0/imm32/false
17024       74/jump-if-= break/disp8
17025       # var is in a float register; ensure type is float
17026       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17027       (simple-mu-type? %eax 0xf)  # float => eax
17028       3d/compare-eax-and 0/imm32/false
17029       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
17030       eb/jump $parse-var-with-type:end/disp8
17031     }
17032     # var is not in a float register; ensure type is not float
17033     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
17034     (simple-mu-type? %eax 0xf)  # float => eax
17035     3d/compare-eax-and 0/imm32/false
17036     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
17037 $parse-var-with-type:end:
17038     # . reclaim locals
17039     81 0/subop/add %esp 8/imm32
17040     # . restore registers
17041     5f/pop-to-edi
17042     5e/pop-to-esi
17043     5b/pop-to-ebx
17044     5a/pop-to-edx
17045     59/pop-to-ecx
17046     58/pop-to-eax
17047     # . epilogue
17048     89/<- %esp 5/r32/ebp
17049     5d/pop-to-ebp
17050     c3/return
17051 
17052 $parse-var-with-type:abort:
17053     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
17054     (write-buffered *(ebp+0x18) "fn ")
17055     (write-buffered *(ebp+0x18) *(ebp+0x14))
17056     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
17057     (flush *(ebp+0x18))
17058     (rewind-stream *(ebp+0xc))
17059     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17060     (write-buffered *(ebp+0x18) "'\n")
17061     (flush *(ebp+0x18))
17062     (stop *(ebp+0x1c) 1)
17063     # never gets here
17064 
17065 $parse-var-with-type:error-float-in-integer-register:
17066     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
17067     (write-buffered *(ebp+0x18) "fn ")
17068     (write-buffered *(ebp+0x18) *(ebp+0x14))
17069     (write-buffered *(ebp+0x18) ": float var '")
17070     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17071     (write-buffered *(ebp+0x18) %eax)
17072     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
17073     (flush *(ebp+0x18))
17074     (stop *(ebp+0x1c) 1)
17075     # never gets here
17076 
17077 $parse-var-with-type:error-non-float-in-floating-point-register:
17078     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
17079     (write-buffered *(ebp+0x18) "fn ")
17080     (write-buffered *(ebp+0x18) *(ebp+0x14))
17081     (write-buffered *(ebp+0x18) ": non-float var '")
17082     (lookup *edi *(edi+4))  # Var-name Var-name => eax
17083     (write-buffered *(ebp+0x18) %eax)
17084     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
17085     (flush *(ebp+0x18))
17086     (stop *(ebp+0x1c) 1)
17087     # never gets here
17088 
17089 float-register?:  # r: (addr array byte) -> result/eax: boolean
17090     # . prologue
17091     55/push-ebp
17092     89/<- %ebp 4/r32/esp
17093     #
17094     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
17095     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
17096     0f 9d/set-if->= %al
17097     25/and-eax-with 0xff/imm32
17098 $float-register?:end:
17099     # . epilogue
17100     89/<- %esp 5/r32/ebp
17101     5d/pop-to-ebp
17102     c3/return
17103 
17104 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17105     # pseudocode:
17106     #   var s: slice = next-mu-token(in)
17107     #   assert s != ""
17108     #   assert s != "->"
17109     #   assert s != "{"
17110     #   assert s != "}"
17111     #   if s == ")"
17112     #     return
17113     #   out = allocate(Type-tree)
17114     #   if s != "("
17115     #     HACK: if s is an int, parse and return it
17116     #     out->is-atom? = true
17117     #     if (s[0] == "_")
17118     #       out->value = type-parameter
17119     #       out->parameter-name = slice-to-string(ad, s)
17120     #     else
17121     #       out->value = pos-or-insert-slice(Type-id, s)
17122     #     return
17123     #   out->left = parse-type(ad, in)
17124     #   out->right = parse-type-tree(ad, in)
17125     #
17126     # . prologue
17127     55/push-ebp
17128     89/<- %ebp 4/r32/esp
17129     # . save registers
17130     50/push-eax
17131     51/push-ecx
17132     52/push-edx
17133     # clear out
17134     (zero-out *(ebp+0x10) *Handle-size)
17135     # var s/ecx: slice
17136     68/push 0/imm32
17137     68/push 0/imm32
17138     89/<- %ecx 4/r32/esp
17139     # s = next-mu-token(in)
17140     (next-mu-token *(ebp+0xc) %ecx)
17141 #?     (write-buffered Stderr "tok: ")
17142 #?     (write-slice-buffered Stderr %ecx)
17143 #?     (write-buffered Stderr "$\n")
17144 #?     (flush Stderr)
17145     # assert s != ""
17146     (slice-equal? %ecx "")  # => eax
17147     3d/compare-eax-and 0/imm32/false
17148     0f 85/jump-if-!= $parse-type:abort/disp32
17149     # assert s != "{"
17150     (slice-equal? %ecx "{")  # => eax
17151     3d/compare-eax-and 0/imm32/false
17152     0f 85/jump-if-!= $parse-type:abort/disp32
17153     # assert s != "}"
17154     (slice-equal? %ecx "}")  # => eax
17155     3d/compare-eax-and 0/imm32/false
17156     0f 85/jump-if-!= $parse-type:abort/disp32
17157     # assert s != "->"
17158     (slice-equal? %ecx "->")  # => eax
17159     3d/compare-eax-and 0/imm32/false
17160     0f 85/jump-if-!= $parse-type:abort/disp32
17161     # if (s == ")") return
17162     (slice-equal? %ecx ")")  # => eax
17163     3d/compare-eax-and 0/imm32/false
17164     0f 85/jump-if-!= $parse-type:end/disp32
17165     # out = new tree
17166     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17167     # var out-addr/edx: (addr type-tree) = lookup(*out)
17168     8b/-> *(ebp+0x10) 2/r32/edx
17169     (lookup *edx *(edx+4))  # => eax
17170     89/<- %edx 0/r32/eax
17171     {
17172       # if (s != "(") break
17173       (slice-equal? %ecx "(")  # => eax
17174       3d/compare-eax-and 0/imm32/false
17175       0f 85/jump-if-!= break/disp32
17176       # if s is a number, store it in the type's size field
17177       {
17178 $parse-type:check-for-int:
17179         # var tmp/eax: byte = *s->slice
17180         8b/-> *ecx 0/r32/eax
17181         8a/copy-byte *eax 0/r32/AL
17182         25/and-eax-with 0xff/imm32
17183         # TODO: raise an error on `var x: (array int a)`
17184         (decimal-digit? %eax)  # => eax
17185         3d/compare-eax-and 0/imm32/false
17186         74/jump-if-= break/disp8
17187 $parse-type:int:
17188         # strip out metadata
17189         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
17190         #
17191         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
17192         (parse-hex-int-from-slice %ecx)  # => eax
17193         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
17194         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
17195         e9/jump $parse-type:end/disp32
17196       }
17197 $parse-type:atom:
17198       # out->is-atom? = true
17199       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
17200       {
17201 $parse-type:check-for-type-parameter:
17202         # var tmp/eax: byte = *s->slice
17203         8b/-> *ecx 0/r32/eax
17204         8a/copy-byte *eax 0/r32/AL
17205         25/and-eax-with 0xff/imm32
17206         # if (tmp != '_') break
17207         3d/compare-eax-and 0x5f/imm32/_
17208         75/jump-if-!= break/disp8
17209 $parse-type:type-parameter:
17210         # out->value = type-parameter
17211         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
17212         # out->parameter-name = slice-to-string(ad, s)
17213         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
17214         (slice-to-string *(ebp+8) %ecx %eax)
17215         e9/jump $parse-type:end/disp32
17216       }
17217 $parse-type:non-type-parameter:
17218       # out->value = pos-or-insert-slice(Type-id, s)
17219       (pos-or-insert-slice Type-id %ecx)  # => eax
17220       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
17221       e9/jump $parse-type:end/disp32
17222     }
17223 $parse-type:non-atom:
17224     # otherwise s == "("
17225     # out->left = parse-type(ad, in)
17226     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
17227     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17228     # out->right = parse-type-tree(ad, in)
17229     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17230     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17231 $parse-type:end:
17232     # . reclaim locals
17233     81 0/subop/add %esp 8/imm32
17234     # . restore registers
17235     5a/pop-to-edx
17236     59/pop-to-ecx
17237     58/pop-to-eax
17238     # . epilogue
17239     89/<- %esp 5/r32/ebp
17240     5d/pop-to-ebp
17241     c3/return
17242 
17243 $parse-type:abort:
17244     # error("unexpected token when parsing type: '" s "'\n")
17245     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
17246     (write-slice-buffered *(ebp+0x14) %ecx)
17247     (write-buffered *(ebp+0x14) "'\n")
17248     (flush *(ebp+0x14))
17249     (stop *(ebp+0x18) 1)
17250     # never gets here
17251 
17252 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
17253     # pseudocode:
17254     #   var tmp: (handle type-tree) = parse-type(ad, in)
17255     #   if tmp == 0
17256     #     return 0
17257     #   out = allocate(Type-tree)
17258     #   out->left = tmp
17259     #   out->right = parse-type-tree(ad, in)
17260     #
17261     # . prologue
17262     55/push-ebp
17263     89/<- %ebp 4/r32/esp
17264     # . save registers
17265     50/push-eax
17266     51/push-ecx
17267     52/push-edx
17268     #
17269     (zero-out *(ebp+0x10) *Handle-size)
17270     # var tmp/ecx: (handle type-tree)
17271     68/push 0/imm32
17272     68/push 0/imm32
17273     89/<- %ecx 4/r32/esp
17274     # tmp = parse-type(ad, in)
17275     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
17276     # if (tmp == 0) return
17277     81 7/subop/compare *ecx 0/imm32
17278     74/jump-if-= $parse-type-tree:end/disp8
17279     # out = new tree
17280     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
17281     # var out-addr/edx: (addr tree) = lookup(*out)
17282     8b/-> *(ebp+0x10) 2/r32/edx
17283     (lookup *edx *(edx+4))  # => eax
17284     89/<- %edx 0/r32/eax
17285     # out->left = tmp
17286     8b/-> *ecx 0/r32/eax
17287     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
17288     8b/-> *(ecx+4) 0/r32/eax
17289     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
17290     # out->right = parse-type-tree(ad, in)
17291     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
17292     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
17293 $parse-type-tree:end:
17294     # . reclaim locals
17295     81 0/subop/add %esp 8/imm32
17296     # . restore registers
17297     5a/pop-to-edx
17298     59/pop-to-ecx
17299     58/pop-to-eax
17300     # . epilogue
17301     89/<- %esp 5/r32/ebp
17302     5d/pop-to-ebp
17303     c3/return
17304 
17305 next-mu-token:  # in: (addr stream byte), out: (addr slice)
17306     # pseudocode:
17307     # start:
17308     #   skip-chars-matching-whitespace(in)
17309     #   if in->read >= in->write              # end of in
17310     #     out = {0, 0}
17311     #     return
17312     #   out->start = &in->data[in->read]
17313     #   var curr-byte/eax: byte = in->data[in->read]
17314     #   if curr->byte == ','                  # comment token
17315     #     ++in->read
17316     #     goto start
17317     #   if curr-byte == '#'                   # comment
17318     #     goto done                             # treat as eof
17319     #   if curr-byte == '"'                   # string literal
17320     #     skip-string(in)
17321     #     goto done                           # no metadata
17322     #   if curr-byte == '('
17323     #     ++in->read
17324     #     goto done
17325     #   if curr-byte == ')'
17326     #     ++in->read
17327     #     goto done
17328     #   # read a word
17329     #   while true
17330     #     if in->read >= in->write
17331     #       break
17332     #     curr-byte = in->data[in->read]
17333     #     if curr-byte == ' '
17334     #       break
17335     #     if curr-byte == '\r'
17336     #       break
17337     #     if curr-byte == '\n'
17338     #       break
17339     #     if curr-byte == '('
17340     #       break
17341     #     if curr-byte == ')'
17342     #       break
17343     #     if curr-byte == ','
17344     #       break
17345     #     ++in->read
17346     # done:
17347     #   out->end = &in->data[in->read]
17348     #
17349     # . prologue
17350     55/push-ebp
17351     89/<- %ebp 4/r32/esp
17352     # . save registers
17353     50/push-eax
17354     51/push-ecx
17355     56/push-esi
17356     57/push-edi
17357     # esi = in
17358     8b/-> *(ebp+8) 6/r32/esi
17359     # edi = out
17360     8b/-> *(ebp+0xc) 7/r32/edi
17361 $next-mu-token:start:
17362     (skip-chars-matching-whitespace %esi)
17363 $next-mu-token:check0:
17364     # if (in->read >= in->write) return out = {0, 0}
17365     # . ecx = in->read
17366     8b/-> *(esi+4) 1/r32/ecx
17367     # . if (ecx >= in->write) return out = {0, 0}
17368     3b/compare<- *esi 1/r32/ecx
17369     c7 0/subop/copy *edi 0/imm32
17370     c7 0/subop/copy *(edi+4) 0/imm32
17371     0f 8d/jump-if->= $next-mu-token:end/disp32
17372     # out->start = &in->data[in->read]
17373     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17374     89/<- *edi 0/r32/eax
17375     # var curr-byte/eax: byte = in->data[in->read]
17376     31/xor-with %eax 0/r32/eax
17377     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17378     {
17379 $next-mu-token:check-for-comma:
17380       # if (curr-byte != ',') break
17381       3d/compare-eax-and 0x2c/imm32/comma
17382       75/jump-if-!= break/disp8
17383       # ++in->read
17384       ff 0/subop/increment *(esi+4)
17385       # restart
17386       e9/jump $next-mu-token:start/disp32
17387     }
17388     {
17389 $next-mu-token:check-for-comment:
17390       # if (curr-byte != '#') break
17391       3d/compare-eax-and 0x23/imm32/pound
17392       75/jump-if-!= break/disp8
17393       # return eof
17394       e9/jump $next-mu-token:done/disp32
17395     }
17396     {
17397 $next-mu-token:check-for-string-literal:
17398       # if (curr-byte != '"') break
17399       3d/compare-eax-and 0x22/imm32/dquote
17400       75/jump-if-!= break/disp8
17401       (skip-string %esi)
17402       # return
17403       e9/jump $next-mu-token:done/disp32
17404     }
17405     {
17406 $next-mu-token:check-for-open-paren:
17407       # if (curr-byte != '(') break
17408       3d/compare-eax-and 0x28/imm32/open-paren
17409       75/jump-if-!= break/disp8
17410       # ++in->read
17411       ff 0/subop/increment *(esi+4)
17412       # return
17413       e9/jump $next-mu-token:done/disp32
17414     }
17415     {
17416 $next-mu-token:check-for-close-paren:
17417       # if (curr-byte != ')') break
17418       3d/compare-eax-and 0x29/imm32/close-paren
17419       75/jump-if-!= break/disp8
17420       # ++in->read
17421       ff 0/subop/increment *(esi+4)
17422       # return
17423       e9/jump $next-mu-token:done/disp32
17424     }
17425     {
17426 $next-mu-token:regular-word-without-metadata:
17427       # if (in->read >= in->write) break
17428       # . ecx = in->read
17429       8b/-> *(esi+4) 1/r32/ecx
17430       # . if (ecx >= in->write) break
17431       3b/compare<- *esi 1/r32/ecx
17432       7d/jump-if->= break/disp8
17433       # var c/eax: byte = in->data[in->read]
17434       31/xor-with %eax 0/r32/eax
17435       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
17436       # if (c == ' ') break
17437       3d/compare-eax-and 0x20/imm32/space
17438       74/jump-if-= break/disp8
17439       # if (c == '\r') break
17440       3d/compare-eax-and 0xd/imm32/carriage-return
17441       74/jump-if-= break/disp8
17442       # if (c == '\n') break
17443       3d/compare-eax-and 0xa/imm32/newline
17444       74/jump-if-= break/disp8
17445       # if (c == '(') break
17446       3d/compare-eax-and 0x28/imm32/open-paren
17447       0f 84/jump-if-= break/disp32
17448       # if (c == ')') break
17449       3d/compare-eax-and 0x29/imm32/close-paren
17450       0f 84/jump-if-= break/disp32
17451       # if (c == ',') break
17452       3d/compare-eax-and 0x2c/imm32/comma
17453       0f 84/jump-if-= break/disp32
17454       # ++in->read
17455       ff 0/subop/increment *(esi+4)
17456       #
17457       e9/jump loop/disp32
17458     }
17459 $next-mu-token:done:
17460     # out->end = &in->data[in->read]
17461     8b/-> *(esi+4) 1/r32/ecx
17462     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
17463     89/<- *(edi+4) 0/r32/eax
17464 $next-mu-token:end:
17465     # . restore registers
17466     5f/pop-to-edi
17467     5e/pop-to-esi
17468     59/pop-to-ecx
17469     58/pop-to-eax
17470     # . epilogue
17471     89/<- %esp 5/r32/ebp
17472     5d/pop-to-ebp
17473     c3/return
17474 
17475 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17476     # . prologue
17477     55/push-ebp
17478     89/<- %ebp 4/r32/esp
17479     # if (pos-slice(arr, s) != -1) return it
17480     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17481     3d/compare-eax-and -1/imm32
17482     75/jump-if-!= $pos-or-insert-slice:end/disp8
17483 $pos-or-insert-slice:insert:
17484     # var s2/eax: (handle array byte)
17485     68/push 0/imm32
17486     68/push 0/imm32
17487     89/<- %eax 4/r32/esp
17488     (slice-to-string Heap *(ebp+0xc) %eax)
17489     # throw away alloc-id
17490     (lookup *eax *(eax+4))  # => eax
17491     (write-int *(ebp+8) %eax)
17492     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
17493 $pos-or-insert-slice:end:
17494     # . reclaim locals
17495     81 0/subop/add %esp 8/imm32
17496     # . epilogue
17497     89/<- %esp 5/r32/ebp
17498     5d/pop-to-ebp
17499     c3/return
17500 
17501 # return the index in an array of strings matching 's', -1 if not found
17502 # index is denominated in elements, not bytes
17503 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
17504     # . prologue
17505     55/push-ebp
17506     89/<- %ebp 4/r32/esp
17507     # . save registers
17508     51/push-ecx
17509     52/push-edx
17510     53/push-ebx
17511     56/push-esi
17512 #?     (write-buffered Stderr "pos-slice: ")
17513 #?     (write-slice-buffered Stderr *(ebp+0xc))
17514 #?     (write-buffered Stderr "\n")
17515 #?     (flush Stderr)
17516     # esi = arr
17517     8b/-> *(ebp+8) 6/r32/esi
17518     # var index/ecx: int = 0
17519     b9/copy-to-ecx 0/imm32
17520     # var curr/edx: (addr (addr array byte)) = arr->data
17521     8d/copy-address *(esi+0xc) 2/r32/edx
17522     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
17523     8b/-> *esi 3/r32/ebx
17524     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
17525     {
17526 #?       (write-buffered Stderr "  ")
17527 #?       (write-int32-hex-buffered Stderr %ecx)
17528 #?       (write-buffered Stderr "\n")
17529 #?       (flush Stderr)
17530       # if (curr >= max) return -1
17531       39/compare %edx 3/r32/ebx
17532       b8/copy-to-eax -1/imm32
17533       73/jump-if-addr>= $pos-slice:end/disp8
17534       # if (slice-equal?(s, *curr)) break
17535       (slice-equal? *(ebp+0xc) *edx)  # => eax
17536       3d/compare-eax-and 0/imm32/false
17537       75/jump-if-!= break/disp8
17538       # ++index
17539       41/increment-ecx
17540       # curr += 4
17541       81 0/subop/add %edx 4/imm32
17542       #
17543       eb/jump loop/disp8
17544     }
17545     # return index
17546     89/<- %eax 1/r32/ecx
17547 $pos-slice:end:
17548 #?     (write-buffered Stderr "=> ")
17549 #?     (write-int32-hex-buffered Stderr %eax)
17550 #?     (write-buffered Stderr "\n")
17551     # . restore registers
17552     5e/pop-to-esi
17553     5b/pop-to-ebx
17554     5a/pop-to-edx
17555     59/pop-to-ecx
17556     # . epilogue
17557     89/<- %esp 5/r32/ebp
17558     5d/pop-to-ebp
17559     c3/return
17560 
17561 test-parse-var-with-type:
17562     # . prologue
17563     55/push-ebp
17564     89/<- %ebp 4/r32/esp
17565     # setup
17566     8b/-> *Primitive-type-ids 0/r32/eax
17567     89/<- *Type-id 0/r32/eax  # stream-write
17568     # (eax..ecx) = "x:"
17569     b8/copy-to-eax "x:"/imm32
17570     8b/-> *eax 1/r32/ecx
17571     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17572     05/add-to-eax 4/imm32
17573     # var slice/ecx: slice = {eax, ecx}
17574     51/push-ecx
17575     50/push-eax
17576     89/<- %ecx 4/r32/esp
17577     # _test-input-stream contains "int"
17578     (clear-stream _test-input-stream)
17579     (write _test-input-stream "int")
17580     # var v/edx: (handle var)
17581     68/push 0/imm32
17582     68/push 0/imm32
17583     89/<- %edx 4/r32/esp
17584     #
17585     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17586     # var v-addr/edx: (addr var) = lookup(v)
17587     (lookup *edx *(edx+4))  # => eax
17588     89/<- %edx 0/r32/eax
17589     # check v-addr->name
17590     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17591     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
17592     # check v-addr->type
17593     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17594     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
17595     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
17596     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
17597     # . epilogue
17598     89/<- %esp 5/r32/ebp
17599     5d/pop-to-ebp
17600     c3/return
17601 
17602 test-parse-var-with-type-and-register:
17603     # . prologue
17604     55/push-ebp
17605     89/<- %ebp 4/r32/esp
17606     # setup
17607     8b/-> *Primitive-type-ids 0/r32/eax
17608     89/<- *Type-id 0/r32/eax  # stream-write
17609     # (eax..ecx) = "x/eax:"
17610     b8/copy-to-eax "x/eax:"/imm32
17611     8b/-> *eax 1/r32/ecx
17612     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17613     05/add-to-eax 4/imm32
17614     # var slice/ecx: slice = {eax, ecx}
17615     51/push-ecx
17616     50/push-eax
17617     89/<- %ecx 4/r32/esp
17618     # _test-input-stream contains "int"
17619     (clear-stream _test-input-stream)
17620     (write _test-input-stream "int")
17621     # var v/edx: (handle var)
17622     68/push 0/imm32
17623     68/push 0/imm32
17624     89/<- %edx 4/r32/esp
17625     #
17626     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17627     # var v-addr/edx: (addr var) = lookup(v)
17628     (lookup *edx *(edx+4))  # => eax
17629     89/<- %edx 0/r32/eax
17630     # check v-addr->name
17631     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17632     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
17633     # check v-addr->register
17634     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17635     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
17636     # check v-addr->type
17637     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17638     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
17639     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
17640     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
17641     # . epilogue
17642     89/<- %esp 5/r32/ebp
17643     5d/pop-to-ebp
17644     c3/return
17645 
17646 test-parse-var-with-trailing-characters:
17647     # . prologue
17648     55/push-ebp
17649     89/<- %ebp 4/r32/esp
17650     # setup
17651     8b/-> *Primitive-type-ids 0/r32/eax
17652     89/<- *Type-id 0/r32/eax  # stream-write
17653     # (eax..ecx) = "x:"
17654     b8/copy-to-eax "x:"/imm32
17655     8b/-> *eax 1/r32/ecx
17656     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17657     05/add-to-eax 4/imm32
17658     # var slice/ecx: slice = {eax, ecx}
17659     51/push-ecx
17660     50/push-eax
17661     89/<- %ecx 4/r32/esp
17662     # _test-input-stream contains "int,"
17663     (clear-stream _test-input-stream)
17664     (write _test-input-stream "int,")
17665     # var v/edx: (handle var)
17666     68/push 0/imm32
17667     68/push 0/imm32
17668     89/<- %edx 4/r32/esp
17669     #
17670     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17671     # var v-addr/edx: (addr var) = lookup(v)
17672     (lookup *edx *(edx+4))  # => eax
17673     89/<- %edx 0/r32/eax
17674     # check v-addr->name
17675     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17676     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
17677     # check v-addr->register
17678     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
17679     # check v-addr->type
17680     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17681     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
17682     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
17683     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
17684     # . epilogue
17685     89/<- %esp 5/r32/ebp
17686     5d/pop-to-ebp
17687     c3/return
17688 
17689 test-parse-var-with-register-and-trailing-characters:
17690     # . prologue
17691     55/push-ebp
17692     89/<- %ebp 4/r32/esp
17693     # setup
17694     8b/-> *Primitive-type-ids 0/r32/eax
17695     89/<- *Type-id 0/r32/eax  # stream-write
17696     # (eax..ecx) = "x/eax:"
17697     b8/copy-to-eax "x/eax:"/imm32
17698     8b/-> *eax 1/r32/ecx
17699     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17700     05/add-to-eax 4/imm32
17701     # var slice/ecx: slice = {eax, ecx}
17702     51/push-ecx
17703     50/push-eax
17704     89/<- %ecx 4/r32/esp
17705     # _test-input-stream contains "int,"
17706     (clear-stream _test-input-stream)
17707     (write _test-input-stream "int,")
17708     # var v/edx: (handle var)
17709     68/push 0/imm32
17710     68/push 0/imm32
17711     89/<- %edx 4/r32/esp
17712     #
17713     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17714     # var v-addr/edx: (addr var) = lookup(v)
17715     (lookup *edx *(edx+4))  # => eax
17716     89/<- %edx 0/r32/eax
17717     # check v-addr->name
17718     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17719     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
17720     # check v-addr->register
17721     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17722     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
17723     # check v-addr->type
17724     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17725     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
17726     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
17727     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
17728     # . epilogue
17729     89/<- %esp 5/r32/ebp
17730     5d/pop-to-ebp
17731     c3/return
17732 
17733 test-parse-var-with-compound-type:
17734     # . prologue
17735     55/push-ebp
17736     89/<- %ebp 4/r32/esp
17737     # setup
17738     8b/-> *Primitive-type-ids 0/r32/eax
17739     89/<- *Type-id 0/r32/eax  # stream-write
17740     # (eax..ecx) = "x:"
17741     b8/copy-to-eax "x:"/imm32
17742     8b/-> *eax 1/r32/ecx
17743     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17744     05/add-to-eax 4/imm32
17745     # var slice/ecx: slice = {eax, ecx}
17746     51/push-ecx
17747     50/push-eax
17748     89/<- %ecx 4/r32/esp
17749     # _test-input-stream contains "(addr int)"
17750     (clear-stream _test-input-stream)
17751     (write _test-input-stream "(addr int)")
17752     # var v/edx: (handle var)
17753     68/push 0/imm32
17754     68/push 0/imm32
17755     89/<- %edx 4/r32/esp
17756     #
17757     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
17758     # var v-addr/edx: (addr var) = lookup(v)
17759     (lookup *edx *(edx+4))  # => eax
17760     89/<- %edx 0/r32/eax
17761     # check v-addr->name
17762     (lookup *edx *(edx+4))  # Var-name Var-name => eax
17763     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
17764     # check v-addr->register
17765     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
17766     # - check v-addr->type
17767     # var type/edx: (addr type-tree) = var->type
17768     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17769     89/<- %edx 0/r32/eax
17770     # type is a non-atom
17771     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
17772     # type->left == atom(addr)
17773     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
17774     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
17775     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
17776     # type->right->left == atom(int)
17777     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
17778     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17779     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
17780     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
17781     # type->right->right == null
17782     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
17783     # . epilogue
17784     89/<- %esp 5/r32/ebp
17785     5d/pop-to-ebp
17786     c3/return
17787 
17788 # identifier starts with a letter or '$' or '_'
17789 # no constraints at the moment on later letters
17790 # all we really want to do so far is exclude '{', '}' and '->'
17791 identifier?:  # in: (addr slice) -> result/eax: boolean
17792     # . prologue
17793     55/push-ebp
17794     89/<- %ebp 4/r32/esp
17795     # if (slice-empty?(in)) return false
17796     (slice-empty? *(ebp+8))  # => eax
17797     3d/compare-eax-and 0/imm32/false
17798     75/jump-if-!= $identifier?:false/disp8
17799     # var c/eax: byte = *in->start
17800     8b/-> *(ebp+8) 0/r32/eax
17801     8b/-> *eax 0/r32/eax
17802     8a/copy-byte *eax 0/r32/AL
17803     25/and-eax-with 0xff/imm32
17804     # if (c == '$') return true
17805     3d/compare-eax-and 0x24/imm32/$
17806     74/jump-if-= $identifier?:true/disp8
17807     # if (c == '_') return true
17808     3d/compare-eax-and 0x5f/imm32/_
17809     74/jump-if-= $identifier?:true/disp8
17810     # drop case
17811     25/and-eax-with 0x5f/imm32
17812     # if (c < 'A') return false
17813     3d/compare-eax-and 0x41/imm32/A
17814     7c/jump-if-< $identifier?:false/disp8
17815     # if (c > 'Z') return false
17816     3d/compare-eax-and 0x5a/imm32/Z
17817     7f/jump-if-> $identifier?:false/disp8
17818     # otherwise return true
17819 $identifier?:true:
17820     b8/copy-to-eax 1/imm32/true
17821     eb/jump $identifier?:end/disp8
17822 $identifier?:false:
17823     b8/copy-to-eax 0/imm32/false
17824 $identifier?:end:
17825     # . epilogue
17826     89/<- %esp 5/r32/ebp
17827     5d/pop-to-ebp
17828     c3/return
17829 
17830 test-is-identifier-dollar:
17831     # . prologue
17832     55/push-ebp
17833     89/<- %ebp 4/r32/esp
17834     # (eax..ecx) = "$a"
17835     b8/copy-to-eax "$a"/imm32
17836     8b/-> *eax 1/r32/ecx
17837     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17838     05/add-to-eax 4/imm32
17839     # var slice/ecx: slice = {eax, ecx}
17840     51/push-ecx
17841     50/push-eax
17842     89/<- %ecx 4/r32/esp
17843     #
17844     (identifier? %ecx)
17845     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
17846     # . epilogue
17847     89/<- %esp 5/r32/ebp
17848     5d/pop-to-ebp
17849     c3/return
17850 
17851 test-is-identifier-underscore:
17852     # . prologue
17853     55/push-ebp
17854     89/<- %ebp 4/r32/esp
17855     # (eax..ecx) = "_a"
17856     b8/copy-to-eax "_a"/imm32
17857     8b/-> *eax 1/r32/ecx
17858     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17859     05/add-to-eax 4/imm32
17860     # var slice/ecx: slice = {eax, ecx}
17861     51/push-ecx
17862     50/push-eax
17863     89/<- %ecx 4/r32/esp
17864     #
17865     (identifier? %ecx)
17866     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
17867     # . epilogue
17868     89/<- %esp 5/r32/ebp
17869     5d/pop-to-ebp
17870     c3/return
17871 
17872 test-is-identifier-a:
17873     # . prologue
17874     55/push-ebp
17875     89/<- %ebp 4/r32/esp
17876     # (eax..ecx) = "a$"
17877     b8/copy-to-eax "a$"/imm32
17878     8b/-> *eax 1/r32/ecx
17879     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17880     05/add-to-eax 4/imm32
17881     # var slice/ecx: slice = {eax, ecx}
17882     51/push-ecx
17883     50/push-eax
17884     89/<- %ecx 4/r32/esp
17885     #
17886     (identifier? %ecx)
17887     (check-ints-equal %eax 1 "F - test-is-identifier-a")
17888     # . epilogue
17889     89/<- %esp 5/r32/ebp
17890     5d/pop-to-ebp
17891     c3/return
17892 
17893 test-is-identifier-z:
17894     # . prologue
17895     55/push-ebp
17896     89/<- %ebp 4/r32/esp
17897     # (eax..ecx) = "z$"
17898     b8/copy-to-eax "z$"/imm32
17899     8b/-> *eax 1/r32/ecx
17900     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17901     05/add-to-eax 4/imm32
17902     # var slice/ecx: slice = {eax, ecx}
17903     51/push-ecx
17904     50/push-eax
17905     89/<- %ecx 4/r32/esp
17906     #
17907     (identifier? %ecx)
17908     (check-ints-equal %eax 1 "F - test-is-identifier-z")
17909     # . epilogue
17910     89/<- %esp 5/r32/ebp
17911     5d/pop-to-ebp
17912     c3/return
17913 
17914 test-is-identifier-A:
17915     # . prologue
17916     55/push-ebp
17917     89/<- %ebp 4/r32/esp
17918     # (eax..ecx) = "A$"
17919     b8/copy-to-eax "A$"/imm32
17920     8b/-> *eax 1/r32/ecx
17921     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17922     05/add-to-eax 4/imm32
17923     # var slice/ecx: slice = {eax, ecx}
17924     51/push-ecx
17925     50/push-eax
17926     89/<- %ecx 4/r32/esp
17927     #
17928     (identifier? %ecx)
17929     (check-ints-equal %eax 1 "F - test-is-identifier-A")
17930     # . epilogue
17931     89/<- %esp 5/r32/ebp
17932     5d/pop-to-ebp
17933     c3/return
17934 
17935 test-is-identifier-Z:
17936     # . prologue
17937     55/push-ebp
17938     89/<- %ebp 4/r32/esp
17939     # (eax..ecx) = "Z$"
17940     b8/copy-to-eax "Z$"/imm32
17941     8b/-> *eax 1/r32/ecx
17942     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17943     05/add-to-eax 4/imm32
17944     # var slice/ecx: slice = {eax, ecx}
17945     51/push-ecx
17946     50/push-eax
17947     89/<- %ecx 4/r32/esp
17948     #
17949     (identifier? %ecx)
17950     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
17951     # . epilogue
17952     89/<- %esp 5/r32/ebp
17953     5d/pop-to-ebp
17954     c3/return
17955 
17956 test-is-identifier-at:
17957     # character before 'A' is invalid
17958     # . prologue
17959     55/push-ebp
17960     89/<- %ebp 4/r32/esp
17961     # (eax..ecx) = "@a"
17962     b8/copy-to-eax "@a"/imm32
17963     8b/-> *eax 1/r32/ecx
17964     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17965     05/add-to-eax 4/imm32
17966     # var slice/ecx: slice = {eax, ecx}
17967     51/push-ecx
17968     50/push-eax
17969     89/<- %ecx 4/r32/esp
17970     #
17971     (identifier? %ecx)
17972     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17973     # . epilogue
17974     89/<- %esp 5/r32/ebp
17975     5d/pop-to-ebp
17976     c3/return
17977 
17978 test-is-identifier-square-bracket:
17979     # character after 'Z' is invalid
17980     # . prologue
17981     55/push-ebp
17982     89/<- %ebp 4/r32/esp
17983     # (eax..ecx) = "[a"
17984     b8/copy-to-eax "[a"/imm32
17985     8b/-> *eax 1/r32/ecx
17986     8d/copy-address *(eax+ecx+4) 1/r32/ecx
17987     05/add-to-eax 4/imm32
17988     # var slice/ecx: slice = {eax, ecx}
17989     51/push-ecx
17990     50/push-eax
17991     89/<- %ecx 4/r32/esp
17992     #
17993     (identifier? %ecx)
17994     (check-ints-equal %eax 0 "F - test-is-identifier-@")
17995     # . epilogue
17996     89/<- %esp 5/r32/ebp
17997     5d/pop-to-ebp
17998     c3/return
17999 
18000 test-is-identifier-backtick:
18001     # character before 'a' is invalid
18002     # . prologue
18003     55/push-ebp
18004     89/<- %ebp 4/r32/esp
18005     # (eax..ecx) = "`a"
18006     b8/copy-to-eax "`a"/imm32
18007     8b/-> *eax 1/r32/ecx
18008     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18009     05/add-to-eax 4/imm32
18010     # var slice/ecx: slice = {eax, ecx}
18011     51/push-ecx
18012     50/push-eax
18013     89/<- %ecx 4/r32/esp
18014     #
18015     (identifier? %ecx)
18016     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
18017     # . epilogue
18018     89/<- %esp 5/r32/ebp
18019     5d/pop-to-ebp
18020     c3/return
18021 
18022 test-is-identifier-curly-brace-open:
18023     # character after 'z' is invalid; also used for blocks
18024     # . prologue
18025     55/push-ebp
18026     89/<- %ebp 4/r32/esp
18027     # (eax..ecx) = "{a"
18028     b8/copy-to-eax "{a"/imm32
18029     8b/-> *eax 1/r32/ecx
18030     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18031     05/add-to-eax 4/imm32
18032     # var slice/ecx: slice = {eax, ecx}
18033     51/push-ecx
18034     50/push-eax
18035     89/<- %ecx 4/r32/esp
18036     #
18037     (identifier? %ecx)
18038     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
18039     # . epilogue
18040     89/<- %esp 5/r32/ebp
18041     5d/pop-to-ebp
18042     c3/return
18043 
18044 test-is-identifier-curly-brace-close:
18045     # . prologue
18046     55/push-ebp
18047     89/<- %ebp 4/r32/esp
18048     # (eax..ecx) = "}a"
18049     b8/copy-to-eax "}a"/imm32
18050     8b/-> *eax 1/r32/ecx
18051     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18052     05/add-to-eax 4/imm32
18053     # var slice/ecx: slice = {eax, ecx}
18054     51/push-ecx
18055     50/push-eax
18056     89/<- %ecx 4/r32/esp
18057     #
18058     (identifier? %ecx)
18059     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
18060     # . epilogue
18061     89/<- %esp 5/r32/ebp
18062     5d/pop-to-ebp
18063     c3/return
18064 
18065 test-is-identifier-hyphen:
18066     # disallow leading '-' since '->' has special meaning
18067     # . prologue
18068     55/push-ebp
18069     89/<- %ebp 4/r32/esp
18070     # (eax..ecx) = "-a"
18071     b8/copy-to-eax "-a"/imm32
18072     8b/-> *eax 1/r32/ecx
18073     8d/copy-address *(eax+ecx+4) 1/r32/ecx
18074     05/add-to-eax 4/imm32
18075     # var slice/ecx: slice = {eax, ecx}
18076     51/push-ecx
18077     50/push-eax
18078     89/<- %ecx 4/r32/esp
18079     #
18080     (identifier? %ecx)
18081     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
18082     # . epilogue
18083     89/<- %esp 5/r32/ebp
18084     5d/pop-to-ebp
18085     c3/return
18086 
18087 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
18088     # . prologue
18089     55/push-ebp
18090     89/<- %ebp 4/r32/esp
18091     # . save registers
18092     50/push-eax
18093     56/push-esi
18094     57/push-edi
18095     # esi = in
18096     8b/-> *(ebp+8) 6/r32/esi
18097     # edi = out
18098     8b/-> *(ebp+0xc) 7/r32/edi
18099     # initialize some global state
18100     c7 0/subop/copy *Curr-block-depth 1/imm32
18101     # parse-mu-block(in, vars, out, out->body)
18102     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
18103     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
18104 $populate-mu-function-body:end:
18105     # . restore registers
18106     5f/pop-to-edi
18107     5e/pop-to-esi
18108     58/pop-to-eax
18109     # . epilogue
18110     89/<- %esp 5/r32/ebp
18111     5d/pop-to-ebp
18112     c3/return
18113 
18114 # parses a block, assuming that the leading '{' has already been read by the caller
18115 parse-mu-block:  # in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle block), err: (addr buffered-file), ed: (addr exit-descriptor)
18116     # pseudocode:
18117     #   var line: (stream byte 512)
18118     #   var word-slice: slice
18119     #   allocate(Heap, Stmt-size, out)
18120     #   var out-addr: (addr block) = lookup(*out)
18121     #   out-addr->tag = 0/block
18122     #   out-addr->var = some unique name
18123     #   push(vars, {out-addr->var, false})
18124     #   while true                                  # line loop
18125     #     clear-stream(line)
18126     #     read-line-buffered(in, line)
18127     #     if (line->write == 0) break               # end of file
18128     #     word-slice = next-mu-token(line)
18129     #     if slice-empty?(word-slice)               # end of line
18130     #       continue
18131     #     else if slice-starts-with?(word-slice, "#")
18132     #       continue
18133     #     else if slice-equal?(word-slice, "{")
18134     #       assert(no-tokens-in(line))
18135     #       block = parse-mu-block(in, vars, fn)
18136     #       append-to-block(out-addr, block)
18137     #     else if slice-equal?(word-slice, "}")
18138     #       break
18139     #     else if slice-ends-with?(word-slice, ":")
18140     #       # TODO: error-check the rest of 'line'
18141     #       --word-slice->end to skip ':'
18142     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
18143     #       append-to-block(out-addr, named-block)
18144     #     else if slice-equal?(word-slice, "var")
18145     #       var-def = parse-mu-var-def(line, vars, fn)
18146     #       append-to-block(out-addr, var-def)
18147     #     else
18148     #       stmt = parse-mu-stmt(line, vars, fn)
18149     #       append-to-block(out-addr, stmt)
18150     #   pop(vars)
18151     #
18152     # . prologue
18153     55/push-ebp
18154     89/<- %ebp 4/r32/esp
18155     # . save registers
18156     50/push-eax
18157     51/push-ecx
18158     52/push-edx
18159     53/push-ebx
18160     57/push-edi
18161     # var line/ecx: (stream byte 512)
18162     81 5/subop/subtract %esp 0x200/imm32
18163     68/push 0x200/imm32/size
18164     68/push 0/imm32/read
18165     68/push 0/imm32/write
18166     89/<- %ecx 4/r32/esp
18167     # var word-slice/edx: slice
18168     68/push 0/imm32/end
18169     68/push 0/imm32/start
18170     89/<- %edx 4/r32/esp
18171     # allocate into out
18172     (allocate Heap *Stmt-size *(ebp+0x14))
18173     # var out-addr/edi: (addr block) = lookup(*out)
18174     8b/-> *(ebp+0x14) 7/r32/edi
18175     (lookup *edi *(edi+4))  # => eax
18176     89/<- %edi 0/r32/eax
18177     # out-addr->tag is 0 (block) by default
18178     # set out-addr->var
18179     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
18180     (new-block-name *(ebp+0x10) %eax)
18181     # push(vars, out-addr->var)
18182     (push *(ebp+0xc) *(edi+0xc))  # Block-var
18183     (push *(ebp+0xc) *(edi+0x10))  # Block-var
18184     (push *(ebp+0xc) 0)  # false
18185     # increment *Curr-block-depth
18186     ff 0/subop/increment *Curr-block-depth
18187     {
18188 $parse-mu-block:line-loop:
18189       # line = read-line-buffered(in)
18190       (clear-stream %ecx)
18191       (read-line-buffered *(ebp+8) %ecx)
18192 #?       (write-buffered Stderr "line: ")
18193 #?       (write-stream-data Stderr %ecx)
18194 #? #?       (write-buffered Stderr Newline)  # line has its own newline
18195 #?       (flush Stderr)
18196 #?       (rewind-stream %ecx)
18197       # if (line->write == 0) break
18198       81 7/subop/compare *ecx 0/imm32
18199       0f 84/jump-if-= break/disp32
18200 #?       (write-buffered Stderr "vars:\n")
18201 #?       (dump-vars *(ebp+0xc))
18202       # word-slice = next-mu-token(line)
18203       (next-mu-token %ecx %edx)
18204 #?       (write-buffered Stderr "word: ")
18205 #?       (write-slice-buffered Stderr %edx)
18206 #?       (write-buffered Stderr Newline)
18207 #?       (flush Stderr)
18208       # if slice-empty?(word-slice) continue
18209       (slice-empty? %edx)
18210       3d/compare-eax-and 0/imm32/false
18211       0f 85/jump-if-!= loop/disp32
18212       # if (slice-starts-with?(word-slice, '#') continue
18213       # . eax = *word-slice->start
18214       8b/-> *edx 0/r32/eax
18215       8a/copy-byte *eax 0/r32/AL
18216       25/and-eax-with 0xff/imm32
18217       # . if (eax == '#') continue
18218       3d/compare-eax-and 0x23/imm32/hash
18219       0f 84/jump-if-= loop/disp32
18220       # if slice-equal?(word-slice, "{")
18221       {
18222 $parse-mu-block:check-for-block:
18223         (slice-equal? %edx "{")
18224         3d/compare-eax-and 0/imm32/false
18225         74/jump-if-= break/disp8
18226         (check-no-tokens-left %ecx)
18227         # parse new block and append
18228         # . var tmp/eax: (handle block)
18229         68/push 0/imm32
18230         68/push 0/imm32
18231         89/<- %eax 4/r32/esp
18232         # .
18233         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18234         (append-to-block Heap %edi  *eax *(eax+4))
18235         # . reclaim tmp
18236         81 0/subop/add %esp 8/imm32
18237         # .
18238         e9/jump $parse-mu-block:line-loop/disp32
18239       }
18240       # if slice-equal?(word-slice, "}") break
18241 $parse-mu-block:check-for-end:
18242       (slice-equal? %edx "}")
18243       3d/compare-eax-and 0/imm32/false
18244       0f 85/jump-if-!= break/disp32
18245       # if slice-ends-with?(word-slice, ":") parse named block and append
18246       {
18247 $parse-mu-block:check-for-named-block:
18248         # . eax = *(word-slice->end-1)
18249         8b/-> *(edx+4) 0/r32/eax
18250         48/decrement-eax
18251         8a/copy-byte *eax 0/r32/AL
18252         25/and-eax-with 0xff/imm32
18253         # . if (eax != ':') break
18254         3d/compare-eax-and 0x3a/imm32/colon
18255         0f 85/jump-if-!= break/disp32
18256         # TODO: error-check the rest of 'line'
18257         #
18258         # skip ':'
18259         ff 1/subop/decrement *(edx+4)  # Slice-end
18260         # var tmp/eax: (handle block)
18261         68/push 0/imm32
18262         68/push 0/imm32
18263         89/<- %eax 4/r32/esp
18264         #
18265         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18266         (append-to-block Heap %edi  *eax *(eax+4))
18267         # reclaim tmp
18268         81 0/subop/add %esp 8/imm32
18269         #
18270         e9/jump $parse-mu-block:line-loop/disp32
18271       }
18272       # if slice-equal?(word-slice, "var")
18273       {
18274 $parse-mu-block:check-for-var:
18275         (slice-equal? %edx "var")
18276         3d/compare-eax-and 0/imm32/false
18277         74/jump-if-= break/disp8
18278         # var tmp/eax: (handle block)
18279         68/push 0/imm32
18280         68/push 0/imm32
18281         89/<- %eax 4/r32/esp
18282         #
18283         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18284         (append-to-block Heap %edi  *eax *(eax+4))
18285         # reclaim tmp
18286         81 0/subop/add %esp 8/imm32
18287         #
18288         e9/jump $parse-mu-block:line-loop/disp32
18289       }
18290 $parse-mu-block:regular-stmt:
18291       # otherwise
18292       # var tmp/eax: (handle block)
18293       68/push 0/imm32
18294       68/push 0/imm32
18295       89/<- %eax 4/r32/esp
18296       #
18297       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
18298       (append-to-block Heap %edi  *eax *(eax+4))
18299       # reclaim tmp
18300       81 0/subop/add %esp 8/imm32
18301       #
18302       e9/jump loop/disp32
18303     } # end line loop
18304     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
18305     # decrement *Curr-block-depth
18306     ff 1/subop/decrement *Curr-block-depth
18307     # pop(vars)
18308     (pop *(ebp+0xc))  # => eax
18309     (pop *(ebp+0xc))  # => eax
18310     (pop *(ebp+0xc))  # => eax
18311 $parse-mu-block:end:
18312     # . reclaim locals
18313     81 0/subop/add %esp 0x214/imm32
18314     # . restore registers
18315     5f/pop-to-edi
18316     5b/pop-to-ebx
18317     5a/pop-to-edx
18318     59/pop-to-ecx
18319     58/pop-to-eax
18320     # . epilogue
18321     89/<- %esp 5/r32/ebp
18322     5d/pop-to-ebp
18323     c3/return
18324 
18325 $parse-mu-block:abort:
18326     # error("'{' or '}' should be on its own line, but got '")
18327     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
18328     (rewind-stream %ecx)
18329     (write-stream-data *(ebp+0x18) %ecx)
18330     (write-buffered *(ebp+0x18) "'\n")
18331     (flush *(ebp+0x18))
18332     (stop *(ebp+0x1c) 1)
18333     # never gets here
18334 
18335 new-block-name:  # fn: (addr function), out: (addr handle var)
18336     # . prologue
18337     55/push-ebp
18338     89/<- %ebp 4/r32/esp
18339     # . save registers
18340     50/push-eax
18341     51/push-ecx
18342     52/push-edx
18343     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
18344     8b/-> *(ebp+8) 0/r32/eax
18345     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18346     8b/-> *eax 0/r32/eax  # String-size
18347     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
18348     89/<- %ecx 0/r32/eax
18349     # var name/edx: (stream byte n)
18350     29/subtract-from %esp 1/r32/ecx
18351     ff 6/subop/push %ecx
18352     68/push 0/imm32/read
18353     68/push 0/imm32/write
18354     89/<- %edx 4/r32/esp
18355     (clear-stream %edx)
18356     # eax = fn->name
18357     8b/-> *(ebp+8) 0/r32/eax
18358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18359     # construct result using Next-block-index (and increment it)
18360     (write %edx "$")
18361     (write %edx %eax)
18362     (write %edx ":")
18363     (write-int32-hex %edx *Next-block-index)
18364     ff 0/subop/increment *Next-block-index
18365     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
18366     # . eax = name->write
18367     8b/-> *edx 0/r32/eax
18368     # . edx = name->data
18369     8d/copy-address *(edx+0xc) 2/r32/edx
18370     # . eax = name->write + name->data
18371     01/add-to %eax 2/r32/edx
18372     # . push {edx, eax}
18373     ff 6/subop/push %eax
18374     ff 6/subop/push %edx
18375     89/<- %eax 4/r32/esp
18376     # out = new literal(s)
18377     (new-literal Heap %eax *(ebp+0xc))
18378 #?     8b/-> *(ebp+0xc) 0/r32/eax
18379 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
18380 #?     (write-int32-hex-buffered Stderr *(eax+8))
18381 #?     (write-buffered Stderr " for var ")
18382 #?     (write-int32-hex-buffered Stderr %eax)
18383 #?     (write-buffered Stderr Newline)
18384 #?     (flush Stderr)
18385 $new-block-name:end:
18386     # . reclaim locals
18387     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
18388     81 0/subop/add %ecx 8/imm32  # slice
18389     01/add-to %esp 1/r32/ecx
18390     # . restore registers
18391     5a/pop-to-edx
18392     59/pop-to-ecx
18393     58/pop-to-eax
18394     # . epilogue
18395     89/<- %esp 5/r32/ebp
18396     5d/pop-to-ebp
18397     c3/return
18398 
18399 check-no-tokens-left:  # line: (addr stream byte)
18400     # . prologue
18401     55/push-ebp
18402     89/<- %ebp 4/r32/esp
18403     # . save registers
18404     50/push-eax
18405     51/push-ecx
18406     # var s/ecx: slice
18407     68/push 0/imm32/end
18408     68/push 0/imm32/start
18409     89/<- %ecx 4/r32/esp
18410     #
18411     (next-mu-token *(ebp+8) %ecx)
18412     # if slice-empty?(s) return
18413     (slice-empty? %ecx)
18414     3d/compare-eax-and 0/imm32/false
18415     75/jump-if-!= $check-no-tokens-left:end/disp8
18416     # if (slice-starts-with?(s, '#') return
18417     # . eax = *s->start
18418     8b/-> *edx 0/r32/eax
18419     8a/copy-byte *eax 0/r32/AL
18420     25/and-eax-with 0xff/imm32
18421     # . if (eax == '#') continue
18422     3d/compare-eax-and 0x23/imm32/hash
18423     74/jump-if-= $check-no-tokens-left:end/disp8
18424     # abort
18425     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
18426     (rewind-stream %ecx)
18427     (write-stream 2 %ecx)
18428     (write-buffered Stderr "'\n")
18429     (flush Stderr)
18430     # . syscall(exit, 1)
18431     bb/copy-to-ebx  1/imm32
18432     e8/call syscall_exit/disp32
18433     # never gets here
18434 $check-no-tokens-left:end:
18435     # . reclaim locals
18436     81 0/subop/add %esp 8/imm32
18437     # . restore registers
18438     59/pop-to-ecx
18439     58/pop-to-eax
18440     # . epilogue
18441     89/<- %esp 5/r32/ebp
18442     5d/pop-to-ebp
18443     c3/return
18444 
18445 parse-mu-named-block:  # name: (addr slice), in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
18446     # pseudocode:
18447     #   var v: (handle var)
18448     #   new-literal(name, v)
18449     #   push(vars, {v, false})
18450     #   parse-mu-block(in, vars, fn, out)
18451     #   pop(vars)
18452     #   out->tag = block
18453     #   out->var = v
18454     #
18455     # . prologue
18456     55/push-ebp
18457     89/<- %ebp 4/r32/esp
18458     # . save registers
18459     50/push-eax
18460     51/push-ecx
18461     57/push-edi
18462     # var v/ecx: (handle var)
18463     68/push 0/imm32
18464     68/push 0/imm32
18465     89/<- %ecx 4/r32/esp
18466     #
18467     (new-literal Heap *(ebp+8) %ecx)
18468     # push(vars, v)
18469     (push *(ebp+0x10) *ecx)
18470     (push *(ebp+0x10) *(ecx+4))
18471     (push *(ebp+0x10) 0)  # false
18472     #
18473     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
18474     # pop v off vars
18475     (pop *(ebp+0x10))  # => eax
18476     (pop *(ebp+0x10))  # => eax
18477     (pop *(ebp+0x10))  # => eax
18478     # var out-addr/edi: (addr stmt) = lookup(*out)
18479     8b/-> *(ebp+0x18) 7/r32/edi
18480     (lookup *edi *(edi+4))  # => eax
18481     89/<- %edi 0/r32/eax
18482     # out-addr->tag = named-block
18483     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
18484     # out-addr->var = v
18485     8b/-> *ecx 0/r32/eax
18486     89/<- *(edi+0xc) 0/r32/eax  # Block-var
18487     8b/-> *(ecx+4) 0/r32/eax
18488     89/<- *(edi+0x10) 0/r32/eax  # Block-var
18489 $parse-mu-named-block:end:
18490     # . reclaim locals
18491     81 0/subop/add %esp 8/imm32
18492     # . restore registers
18493     5f/pop-to-edi
18494     59/pop-to-ecx
18495     58/pop-to-eax
18496     # . epilogue
18497     89/<- %esp 5/r32/ebp
18498     5d/pop-to-ebp
18499     c3/return
18500 
18501 parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack live-var), out: (addr handle stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18502     # . prologue
18503     55/push-ebp
18504     89/<- %ebp 4/r32/esp
18505     # . save registers
18506     50/push-eax
18507     51/push-ecx
18508     52/push-edx
18509     56/push-esi
18510     57/push-edi
18511     # edi = out
18512     8b/-> *(ebp+0x10) 7/r32/edi
18513     # var word-slice/ecx: slice
18514     68/push 0/imm32/end
18515     68/push 0/imm32/start
18516     89/<- %ecx 4/r32/esp
18517     # var v/edx: (handle var)
18518     68/push 0/imm32
18519     68/push 0/imm32
18520     89/<- %edx 4/r32/esp
18521     # v = parse-var-with-type(next-mu-token(line))
18522     (next-mu-token *(ebp+8) %ecx)
18523     {
18524       # just for tests, support null fn
18525       8b/-> *(ebp+0x14) 0/r32/eax
18526       3d/compare-eax-and 0/imm32
18527       74/jump-if-= break/disp8
18528       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18529     }
18530     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
18531     # var v-addr/esi: (addr var)
18532     (lookup *edx *(edx+4))  # => eax
18533     89/<- %esi 0/r32/eax
18534     # v->block-depth = *Curr-block-depth
18535     8b/-> *Curr-block-depth 0/r32/eax
18536     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
18537     # either v has no register and there's no more to this line
18538     81 7/subop/compare *(esi+0x18) 0/imm32
18539     {
18540       75/jump-if-!= break/disp8
18541       # if v-addr->type == byte, abort
18542       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18543       (simple-mu-type? %eax 8)  # byte => eax
18544       3d/compare-eax-and 0/imm32/false
18545       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
18546       # ensure that there's nothing else on this line
18547       (next-mu-token *(ebp+8) %ecx)
18548       (slice-empty? %ecx)  # => eax
18549       3d/compare-eax-and 0/imm32/false
18550       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
18551       #
18552       (new-var-def Heap  *edx *(edx+4)  %edi)
18553       e9/jump $parse-mu-var-def:update-vars/disp32
18554     }
18555     # or v has a register and there's more to this line
18556     {
18557       0f 84/jump-if-= break/disp32
18558       # if v-addr->type == byte, check for unsupported registers
18559       {
18560         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
18561         (simple-mu-type? %eax 8)  # byte => eax
18562         3d/compare-eax-and 0/imm32/false
18563         74/jump-if-= break/disp8
18564         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18565         (string-equal? %eax "esi")  # => eax
18566         3d/compare-eax-and 0/imm32/false
18567         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18568         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
18569         (string-equal? %eax "edi")  # => eax
18570         3d/compare-eax-and 0/imm32/false
18571         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
18572       }
18573       # TODO: vars of type 'byte' should only be initialized by clearing to 0
18574       # ensure that the next word is '<-'
18575       (next-mu-token *(ebp+8) %ecx)
18576       (slice-equal? %ecx "<-")  # => eax
18577       3d/compare-eax-and 0/imm32/false
18578       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
18579       #
18580       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
18581       (lookup *edi *(edi+4))  # => eax
18582       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18583     }
18584 $parse-mu-var-def:update-vars:
18585     # push 'v' at end of function
18586     (push *(ebp+0xc) *edx)
18587     (push *(ebp+0xc) *(edx+4))
18588     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
18589 $parse-mu-var-def:end:
18590     # . reclaim locals
18591     81 0/subop/add %esp 0x10/imm32
18592     # . restore registers
18593     5f/pop-to-edi
18594     5e/pop-to-esi
18595     5a/pop-to-edx
18596     59/pop-to-ecx
18597     58/pop-to-eax
18598     # . epilogue
18599     89/<- %esp 5/r32/ebp
18600     5d/pop-to-ebp
18601     c3/return
18602 
18603 $parse-mu-var-def:error1:
18604     (rewind-stream *(ebp+8))
18605     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
18606     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
18607     (flush *(ebp+0x18))
18608     (write-stream-data *(ebp+0x18) *(ebp+8))
18609     (write-buffered *(ebp+0x18) "'\n")
18610     (flush *(ebp+0x18))
18611     (stop *(ebp+0x1c) 1)
18612     # never gets here
18613 
18614 $parse-mu-var-def:error2:
18615     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
18616     (write-buffered *(ebp+0x18) "fn ")
18617     8b/-> *(ebp+0x14) 0/r32/eax
18618     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18619     (write-buffered *(ebp+0x18) %eax)
18620     (write-buffered *(ebp+0x18) ": var ")
18621     # var v-addr/eax: (addr var) = lookup(v)
18622     (lookup *edx *(edx+4))  # => eax
18623     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18624     (write-buffered *(ebp+0x18) %eax)
18625     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
18626     (flush *(ebp+0x18))
18627     (stop *(ebp+0x1c) 1)
18628     # never gets here
18629 
18630 $parse-mu-var-def:error-byte-on-stack:
18631     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
18632     (write-buffered *(ebp+0x18) "fn ")
18633     8b/-> *(ebp+0x14) 0/r32/eax
18634     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18635     (write-buffered *(ebp+0x18) %eax)
18636     (write-buffered *(ebp+0x18) ": var '")
18637     # var v-addr/eax: (addr var) = lookup(v)
18638     (lookup *edx *(edx+4))  # => eax
18639     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18640     (write-buffered *(ebp+0x18) %eax)
18641     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
18642     (flush *(ebp+0x18))
18643     (stop *(ebp+0x1c) 1)
18644     # never gets here
18645 
18646 $parse-mu-var-def:error-byte-registers:
18647     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
18648     (write-buffered *(ebp+0x18) "fn ")
18649     8b/-> *(ebp+0x14) 0/r32/eax
18650     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18651     (write-buffered *(ebp+0x18) %eax)
18652     (write-buffered *(ebp+0x18) ": var '")
18653     # var v-addr/eax: (addr var) = lookup(v)
18654     (lookup *edx *(edx+4))  # => eax
18655     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18656     (write-buffered *(ebp+0x18) %eax)
18657     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
18658     (flush *(ebp+0x18))
18659     (stop *(ebp+0x1c) 1)
18660     # never gets here
18661 
18662 test-parse-mu-var-def:
18663     # 'var n: int'
18664     # . prologue
18665     55/push-ebp
18666     89/<- %ebp 4/r32/esp
18667     # setup
18668     8b/-> *Primitive-type-ids 0/r32/eax
18669     89/<- *Type-id 0/r32/eax  # stream-write
18670     (clear-stream _test-input-stream)
18671     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
18672     c7 0/subop/copy *Curr-block-depth 1/imm32
18673     # var out/esi: (handle stmt)
18674     68/push 0/imm32
18675     68/push 0/imm32
18676     89/<- %esi 4/r32/esp
18677     # var vars/ecx: (stack (addr var) 16)
18678     81 5/subop/subtract %esp 0xc0/imm32
18679     68/push 0xc0/imm32/size
18680     68/push 0/imm32/top
18681     89/<- %ecx 4/r32/esp
18682     (clear-stack %ecx)
18683     # convert
18684     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18685     # var out-addr/esi: (addr stmt)
18686     (lookup *esi *(esi+4))  # => eax
18687     89/<- %esi 0/r32/eax
18688     #
18689     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
18690     # var v/ecx: (addr var) = lookup(out->var)
18691     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
18692     89/<- %ecx 0/r32/eax
18693     # v->name
18694     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18695     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
18696     # v->register
18697     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
18698     # v->block-depth
18699     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
18700     # v->type == int
18701     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18702     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
18703     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
18704     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
18705     # . epilogue
18706     89/<- %esp 5/r32/ebp
18707     5d/pop-to-ebp
18708     c3/return
18709 
18710 test-parse-mu-reg-var-def:
18711     # 'var n/eax: int <- copy 0'
18712     # . prologue
18713     55/push-ebp
18714     89/<- %ebp 4/r32/esp
18715     # setup
18716     8b/-> *Primitive-type-ids 0/r32/eax
18717     89/<- *Type-id 0/r32/eax  # stream-write
18718     (clear-stream _test-input-stream)
18719     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
18720     c7 0/subop/copy *Curr-block-depth 1/imm32
18721     # var out/esi: (handle stmt)
18722     68/push 0/imm32
18723     68/push 0/imm32
18724     89/<- %esi 4/r32/esp
18725     # var vars/ecx: (stack (addr var) 16)
18726     81 5/subop/subtract %esp 0xc0/imm32
18727     68/push 0xc0/imm32/size
18728     68/push 0/imm32/top
18729     89/<- %ecx 4/r32/esp
18730     (clear-stack %ecx)
18731     # convert
18732     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
18733     # var out-addr/esi: (addr stmt)
18734     (lookup *esi *(esi+4))  # => eax
18735     89/<- %esi 0/r32/eax
18736     #
18737     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
18738     # var v/ecx: (addr var) = lookup(out->outputs->value)
18739     # . eax: (addr stmt-var) = lookup(out->outputs)
18740     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
18741     # .
18742     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
18743     # . eax: (addr var) = lookup(eax->value)
18744     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18745     # . ecx = eax
18746     89/<- %ecx 0/r32/eax
18747     # v->name
18748     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18749     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
18750     # v->register
18751     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
18752     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
18753     # v->block-depth
18754     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
18755     # v->type == int
18756     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18757     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
18758     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
18759     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
18760     # . epilogue
18761     89/<- %esp 5/r32/ebp
18762     5d/pop-to-ebp
18763     c3/return
18764 
18765 parse-mu-stmt:  # line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
18766     # pseudocode:
18767     #   var name: slice
18768     #   allocate(Heap, Stmt-size, out)
18769     #   var out-addr: (addr stmt) = lookup(*out)
18770     #   out-addr->tag = stmt
18771     #   if stmt-has-outputs?(line)
18772     #     while true
18773     #       name = next-mu-token(line)
18774     #       if (name == '<-') break
18775     #       assert(identifier?(name))
18776     #       var v: (handle var) = lookup-var(name, vars)
18777     #       out-addr->outputs = append(v, out-addr->outputs)
18778     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
18779     #
18780     # . prologue
18781     55/push-ebp
18782     89/<- %ebp 4/r32/esp
18783     # . save registers
18784     50/push-eax
18785     51/push-ecx
18786     52/push-edx
18787     53/push-ebx
18788     57/push-edi
18789     # var name/ecx: slice
18790     68/push 0/imm32/end
18791     68/push 0/imm32/start
18792     89/<- %ecx 4/r32/esp
18793     # var is-deref?/edx: boolean = false
18794     ba/copy-to-edx 0/imm32/false
18795     # var v: (handle var)
18796     68/push 0/imm32
18797     68/push 0/imm32
18798     89/<- %ebx 4/r32/esp
18799     #
18800     (allocate Heap *Stmt-size *(ebp+0x14))
18801     # var out-addr/edi: (addr stmt) = lookup(*out)
18802     8b/-> *(ebp+0x14) 7/r32/edi
18803     (lookup *edi *(edi+4))  # => eax
18804     89/<- %edi 0/r32/eax
18805     # out-addr->tag = 1/stmt
18806     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
18807     {
18808       (stmt-has-outputs? *(ebp+8))
18809       3d/compare-eax-and 0/imm32/false
18810       0f 84/jump-if-= break/disp32
18811       {
18812 $parse-mu-stmt:read-outputs:
18813         # name = next-mu-token(line)
18814         (next-mu-token *(ebp+8) %ecx)
18815         # if slice-empty?(word-slice) break
18816         (slice-empty? %ecx)  # => eax
18817         3d/compare-eax-and 0/imm32/false
18818         0f 85/jump-if-!= break/disp32
18819         # if (name == "<-") break
18820         (slice-equal? %ecx "<-")  # => eax
18821         3d/compare-eax-and 0/imm32/false
18822         0f 85/jump-if-!= break/disp32
18823         # if slice-starts-with?(name, "*") abort
18824         8b/-> *ecx 0/r32/eax  # Slice-start
18825         8a/copy-byte *eax 0/r32/AL
18826         25/and-eax-with 0xff/imm32
18827         3d/compare-eax-and 0x2a/imm32/asterisk
18828         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
18829         # assert(identifier?(name))
18830         (identifier? %ecx)  # => eax
18831         3d/compare-eax-and 0/imm32/false
18832         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
18833         #
18834         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18835         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
18836         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
18837         #
18838         e9/jump loop/disp32
18839       }
18840     }
18841     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
18842 $parse-mu-stmt:end:
18843     # . reclaim locals
18844     81 0/subop/add %esp 0x10/imm32
18845     # . restore registers
18846     5f/pop-to-edi
18847     5b/pop-to-ebx
18848     5a/pop-to-edx
18849     59/pop-to-ecx
18850     58/pop-to-eax
18851     # . epilogue
18852     89/<- %esp 5/r32/ebp
18853     5d/pop-to-ebp
18854     c3/return
18855 
18856 $parse-mu-stmt:abort:
18857     # error("invalid identifier '" name "'\n")
18858     (write-buffered *(ebp+0x18) "fn ")
18859     8b/-> *(ebp+0x10) 0/r32/eax
18860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18861     (write-buffered *(ebp+0x18) %eax)
18862     (write-buffered *(ebp+0x18) ": invalid identifier '")
18863     (write-slice-buffered *(ebp+0x18) %ecx)
18864     (write-buffered *(ebp+0x18) "'\n")
18865     (flush *(ebp+0x18))
18866     (stop *(ebp+0x1c) 1)
18867     # never gets here
18868 
18869 $parse-mu-stmt:error-output-dereferenced:
18870     # error("invalid identifier '" name "'\n")
18871     (write-buffered *(ebp+0x18) "fn ")
18872     8b/-> *(ebp+0x10) 0/r32/eax
18873     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18874     (write-buffered *(ebp+0x18) %eax)
18875     (write-buffered *(ebp+0x18) ": output '")
18876     (write-slice-buffered *(ebp+0x18) %ecx)
18877     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
18878     (flush *(ebp+0x18))
18879     (stop *(ebp+0x1c) 1)
18880     # never gets here
18881 
18882 add-operation-and-inputs-to-stmt:  # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18883     # pseudocode:
18884     #   stmt->name = slice-to-string(next-mu-token(line))
18885     #   while true
18886     #     name = next-mu-token(line)
18887     #     v = lookup-var-or-literal(name)
18888     #     stmt->inouts = append(v, stmt->inouts)
18889     #
18890     # . prologue
18891     55/push-ebp
18892     89/<- %ebp 4/r32/esp
18893     # . save registers
18894     50/push-eax
18895     51/push-ecx
18896     52/push-edx
18897     53/push-ebx
18898     56/push-esi
18899     57/push-edi
18900     # edi = stmt
18901     8b/-> *(ebp+8) 7/r32/edi
18902     # var name/ecx: slice
18903     68/push 0/imm32/end
18904     68/push 0/imm32/start
18905     89/<- %ecx 4/r32/esp
18906     # var is-deref?/edx: boolean = false
18907     ba/copy-to-edx 0/imm32/false
18908     # var v/esi: (handle var)
18909     68/push 0/imm32
18910     68/push 0/imm32
18911     89/<- %esi 4/r32/esp
18912 $add-operation-and-inputs-to-stmt:read-operation:
18913     (next-mu-token *(ebp+0xc) %ecx)
18914     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
18915     (slice-to-string Heap %ecx %eax)
18916     # var is-get?/ebx: boolean = (name == "get")
18917     (slice-equal? %ecx "get")  # => eax
18918     89/<- %ebx 0/r32/eax
18919     {
18920 $add-operation-and-inputs-to-stmt:read-inouts:
18921       # name = next-mu-token(line)
18922       (next-mu-token *(ebp+0xc) %ecx)
18923       # if slice-empty?(word-slice) break
18924       (slice-empty? %ecx)  # => eax
18925       3d/compare-eax-and 0/imm32/false
18926       0f 85/jump-if-!= break/disp32
18927       # if (name == "<-") abort
18928       (slice-equal? %ecx "<-")
18929       3d/compare-eax-and 0/imm32/false
18930       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
18931       # if (get? && second operand) lookup or create offset
18932       {
18933         81 7/subop/compare %ebx 0/imm32/false
18934         74/jump-if-= break/disp8
18935         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18936         3d/compare-eax-and 0/imm32
18937         74/jump-if-= break/disp8
18938         (lookup-or-create-constant %eax %ecx %esi)
18939 #?         (lookup *esi *(esi+4))
18940 #?         (write-buffered Stderr "creating new output var ")
18941 #?         (write-int32-hex-buffered Stderr %eax)
18942 #?         (write-buffered Stderr " for field called ")
18943 #?         (write-slice-buffered Stderr %ecx)
18944 #?         (write-buffered Stderr "; var name ")
18945 #?         (lookup *eax *(eax+4))  # Var-name
18946 #?         (write-buffered Stderr %eax)
18947 #?         (write-buffered Stderr Newline)
18948 #?         (flush Stderr)
18949         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
18950       }
18951       # is-deref? = false
18952       ba/copy-to-edx 0/imm32/false
18953       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
18954       8b/-> *ecx 0/r32/eax  # Slice-start
18955       8a/copy-byte *eax 0/r32/AL
18956       25/and-eax-with 0xff/imm32
18957       3d/compare-eax-and 0x2a/imm32/asterisk
18958       {
18959         75/jump-if-!= break/disp8
18960 $add-operation-and-inputs-to-stmt:inout-is-deref:
18961         ff 0/subop/increment *ecx
18962         ba/copy-to-edx 1/imm32/true
18963       }
18964       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18965       # if (deref?) some additional checks
18966       81 7/subop/compare %edx 0/imm32/false
18967       {
18968         74/jump-if-= break/disp8
18969         # if var is not in register, abort
18970         (lookup *esi *(esi+4))  # => eax
18971         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
18972         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
18973         # if var is not an address, abort
18974         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18975         (mu-addr-type? %eax)  # => eax
18976         3d/compare-eax-and 0/imm32/false
18977         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
18978       }
18979 $add-operation-and-inputs-to-stmt:save-var:
18980       8d/copy-address *(edi+0xc) 0/r32/eax
18981       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
18982       #
18983       e9/jump loop/disp32
18984     }
18985 $add-operation-and-inputs-to-stmt:end:
18986     # . reclaim locals
18987     81 0/subop/add %esp 0x10/imm32
18988     # . restore registers
18989     5f/pop-to-edi
18990     5e/pop-to-esi
18991     5b/pop-to-ebx
18992     5a/pop-to-edx
18993     59/pop-to-ecx
18994     58/pop-to-eax
18995     # . epilogue
18996     89/<- %esp 5/r32/ebp
18997     5d/pop-to-ebp
18998     c3/return
18999 
19000 $add-operation-and-inputs-to-stmt:abort:
19001     # error("fn ___: invalid identifier in '" line "'\n")
19002     (write-buffered *(ebp+0x18) "fn ")
19003     8b/-> *(ebp+0x14) 0/r32/eax
19004     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19005     (write-buffered *(ebp+0x18) %eax)
19006     (rewind-stream *(ebp+0xc))
19007     (write-buffered *(ebp+0x18) ": invalid identifier in '")
19008     (write-stream-data *(ebp+0x18) *(ebp+0xc))
19009     (write-buffered *(ebp+0x18) "'\n")
19010     (flush *(ebp+0x18))
19011     (stop *(ebp+0x1c) 1)
19012     # never gets here
19013 
19014 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
19015     # error("fn ___: cannot dereference var ___ on stack\n")
19016     (write-buffered *(ebp+0x18) "fn ")
19017     8b/-> *(ebp+0x14) 0/r32/eax
19018     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19019     (write-buffered *(ebp+0x18) %eax)
19020     (rewind-stream *(ebp+0xc))
19021     (write-buffered *(ebp+0x18) ": cannot dereference var '")
19022     (lookup *esi *(esi+4))  # => eax
19023     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19024     (write-buffered *(ebp+0x18) %eax)
19025     (write-buffered *(ebp+0x18) "' on stack\n")
19026     (flush *(ebp+0x18))
19027     (stop *(ebp+0x1c) 1)
19028     # never gets here
19029 
19030 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
19031     # error("fn ___: cannot dereference non-addr var ___\n")
19032     (write-buffered *(ebp+0x18) "fn ")
19033     8b/-> *(ebp+0x14) 0/r32/eax
19034     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19035     (write-buffered *(ebp+0x18) %eax)
19036     (rewind-stream *(ebp+0xc))
19037     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
19038     (lookup *esi *(esi+4))  # => eax
19039     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19040     (write-buffered *(ebp+0x18) %eax)
19041     (write-buffered *(ebp+0x18) "'\n")
19042     (flush *(ebp+0x18))
19043     (stop *(ebp+0x1c) 1)
19044     # never gets here
19045 
19046 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
19047     # . prologue
19048     55/push-ebp
19049     89/<- %ebp 4/r32/esp
19050     # . save registers
19051     51/push-ecx
19052     # var word-slice/ecx: slice
19053     68/push 0/imm32/end
19054     68/push 0/imm32/start
19055     89/<- %ecx 4/r32/esp
19056     # result = false
19057     b8/copy-to-eax 0/imm32/false
19058     (rewind-stream *(ebp+8))
19059     {
19060       (next-mu-token *(ebp+8) %ecx)
19061       # if slice-empty?(word-slice) break
19062       (slice-empty? %ecx)
19063       3d/compare-eax-and 0/imm32/false
19064       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19065       0f 85/jump-if-!= break/disp32
19066       # if slice-starts-with?(word-slice, '#') break
19067       # . eax = *word-slice->start
19068       8b/-> *ecx 0/r32/eax
19069       8a/copy-byte *eax 0/r32/AL
19070       25/and-eax-with 0xff/imm32
19071       # . if (eax == '#') break
19072       3d/compare-eax-and 0x23/imm32/hash
19073       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
19074       0f 84/jump-if-= break/disp32
19075       # if slice-equal?(word-slice, '<-') return true
19076       (slice-equal? %ecx "<-")
19077       3d/compare-eax-and 0/imm32/false
19078       74/jump-if-= loop/disp8
19079       b8/copy-to-eax 1/imm32/true
19080     }
19081 $stmt-has-outputs:end:
19082     (rewind-stream *(ebp+8))
19083     # . reclaim locals
19084     81 0/subop/add %esp 8/imm32
19085     # . restore registers
19086     59/pop-to-ecx
19087     # . epilogue
19088     89/<- %esp 5/r32/ebp
19089     5d/pop-to-ebp
19090     c3/return
19091 
19092 # if 'name' starts with a digit, create a new literal var for it
19093 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
19094 lookup-var-or-literal:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19095     # . prologue
19096     55/push-ebp
19097     89/<- %ebp 4/r32/esp
19098     # . save registers
19099     50/push-eax
19100     51/push-ecx
19101     56/push-esi
19102     # esi = name
19103     8b/-> *(ebp+8) 6/r32/esi
19104     # if slice-empty?(name) abort
19105     (slice-empty? %esi)  # => eax
19106     3d/compare-eax-and 0/imm32/false
19107     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
19108     # var c/ecx: byte = *name->start
19109     8b/-> *esi 1/r32/ecx
19110     8a/copy-byte *ecx 1/r32/CL
19111     81 4/subop/and %ecx 0xff/imm32
19112     # if (decimal-digit?(c) || c == '-') return new var(name)
19113     {
19114       81 7/subop/compare %ecx 0x2d/imm32/dash
19115       74/jump-if-= $lookup-var-or-literal:literal/disp8
19116       (decimal-digit? %ecx)  # => eax
19117       3d/compare-eax-and 0/imm32/false
19118       74/jump-if-= break/disp8
19119 $lookup-var-or-literal:literal:
19120       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19121       eb/jump $lookup-var-or-literal:end/disp8
19122     }
19123     # else if (c == '"') return new var(name)
19124     {
19125       81 7/subop/compare %ecx 0x22/imm32/dquote
19126       75/jump-if-!= break/disp8
19127 $lookup-var-or-literal:literal-string:
19128       (new-literal-string Heap %esi *(ebp+0x10))
19129       eb/jump $lookup-var-or-literal:end/disp8
19130     }
19131     # otherwise return lookup-var(name, vars)
19132     {
19133 $lookup-var-or-literal:var:
19134       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19135     }
19136 $lookup-var-or-literal:end:
19137     # . restore registers
19138     5e/pop-to-esi
19139     59/pop-to-ecx
19140     58/pop-to-eax
19141     # . epilogue
19142     89/<- %esp 5/r32/ebp
19143     5d/pop-to-ebp
19144     c3/return
19145 
19146 $lookup-var-or-literal:abort:
19147     (write-buffered *(ebp+0x18) "fn ")
19148     8b/-> *(ebp+0x14) 0/r32/eax
19149     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19150     (write-buffered *(ebp+0x18) %eax)
19151     (write-buffered *(ebp+0x18) ": empty variable!")
19152     (flush *(ebp+0x18))
19153     (stop *(ebp+0x1c) 1)
19154     # never gets here
19155 
19156 # return first 'name' from the top (back) of 'vars' and abort if not found
19157 lookup-var:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19158     # . prologue
19159     55/push-ebp
19160     89/<- %ebp 4/r32/esp
19161     # . save registers
19162     50/push-eax
19163     #
19164     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
19165     # if (*out == 0) abort
19166     8b/-> *(ebp+0x10) 0/r32/eax
19167     81 7/subop/compare *eax 0/imm32
19168     74/jump-if-= $lookup-var:abort/disp8
19169 $lookup-var:end:
19170     # . restore registers
19171     58/pop-to-eax
19172     # . epilogue
19173     89/<- %esp 5/r32/ebp
19174     5d/pop-to-ebp
19175     c3/return
19176 
19177 $lookup-var:abort:
19178     (write-buffered *(ebp+0x18) "fn ")
19179     8b/-> *(ebp+0x14) 0/r32/eax
19180     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19181     (write-buffered *(ebp+0x18) %eax)
19182     (write-buffered *(ebp+0x18) ": unknown variable '")
19183     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19184     (write-buffered *(ebp+0x18) "'\n")
19185     (flush *(ebp+0x18))
19186     (stop *(ebp+0x1c) 1)
19187     # never gets here
19188 
19189 # return first 'name' from the top (back) of 'vars', and 0/null if not found
19190 # ensure that 'name' if in a register is the topmost variable in that register
19191 lookup-var-helper:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19192     # pseudocode:
19193     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19194     #   var min = vars->data
19195     #   while curr >= min
19196     #     var v: (handle var) = *curr
19197     #     if v->name == name
19198     #       return
19199     #     curr -= 12
19200     #
19201     # . prologue
19202     55/push-ebp
19203     89/<- %ebp 4/r32/esp
19204     # . save registers
19205     50/push-eax
19206     51/push-ecx
19207     52/push-edx
19208     53/push-ebx
19209     56/push-esi
19210     57/push-edi
19211     # clear out
19212     (zero-out *(ebp+0x10) *Handle-size)
19213     # esi = vars
19214     8b/-> *(ebp+0xc) 6/r32/esi
19215     # ebx = vars->top
19216     8b/-> *esi 3/r32/ebx
19217     # if (vars->top > vars->size) abort
19218     3b/compare<- *(esi+4) 0/r32/eax
19219     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
19220     # var min/edx: (addr handle var) = vars->data
19221     8d/copy-address *(esi+8) 2/r32/edx
19222     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19223     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19224     # var var-in-reg/edi: 16 addrs
19225     68/push 0/imm32
19226     68/push 0/imm32
19227     68/push 0/imm32
19228     68/push 0/imm32
19229     68/push 0/imm32
19230     68/push 0/imm32
19231     68/push 0/imm32
19232     68/push 0/imm32
19233     68/push 0/imm32
19234     68/push 0/imm32
19235     68/push 0/imm32
19236     68/push 0/imm32
19237     68/push 0/imm32
19238     68/push 0/imm32
19239     68/push 0/imm32
19240     68/push 0/imm32
19241     89/<- %edi 4/r32/esp
19242     {
19243 $lookup-var-helper:loop:
19244       # if (curr < min) return
19245       39/compare %ebx 2/r32/edx
19246       0f 82/jump-if-addr< break/disp32
19247       # var v/ecx: (addr var) = lookup(*curr)
19248       (lookup *ebx *(ebx+4))  # => eax
19249       89/<- %ecx 0/r32/eax
19250       # var vn/eax: (addr array byte) = lookup(v->name)
19251       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
19252       # if (vn == name) return curr
19253       (slice-equal? *(ebp+8) %eax)  # => eax
19254       3d/compare-eax-and 0/imm32/false
19255       {
19256         74/jump-if-= break/disp8
19257 $lookup-var-helper:found:
19258         # var vr/eax: (addr array byte) = lookup(v->register)
19259         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19260         3d/compare-eax-and 0/imm32
19261         {
19262           74/jump-if-= break/disp8
19263 $lookup-var-helper:found-register:
19264           # var reg/eax: int = get(Registers, vr)
19265           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19266           8b/-> *eax 0/r32/eax
19267           # if (var-in-reg[reg]) error
19268           8b/-> *(edi+eax<<2) 0/r32/eax
19269           3d/compare-eax-and 0/imm32
19270           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
19271         }
19272 $lookup-var-helper:return:
19273         # esi = out
19274         8b/-> *(ebp+0x10) 6/r32/esi
19275         # *out = *curr
19276         8b/-> *ebx 0/r32/eax
19277         89/<- *esi 0/r32/eax
19278         8b/-> *(ebx+4) 0/r32/eax
19279         89/<- *(esi+4) 0/r32/eax
19280         # return
19281         eb/jump $lookup-var-helper:end/disp8
19282       }
19283       # 'name' not yet found; update var-in-reg if v in register
19284       # . var vr/eax: (addr array byte) = lookup(v->register)
19285       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
19286       # . if (vr == 0) continue
19287       3d/compare-eax-and 0/imm32
19288       74/jump-if-= $lookup-var-helper:continue/disp8
19289       # . var reg/eax: int = get(Registers, vr)
19290       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
19291       8b/-> *eax 0/r32/eax
19292       # . var-in-reg[reg] = v
19293       89/<- *(edi+eax<<2) 1/r32/ecx
19294 $lookup-var-helper:continue:
19295       # curr -= 12
19296       81 5/subop/subtract %ebx 0xc/imm32
19297       e9/jump loop/disp32
19298     }
19299 $lookup-var-helper:end:
19300     # . reclaim locals
19301     81 0/subop/add %esp 0x40/imm32
19302     # . restore registers
19303     5f/pop-to-edi
19304     5e/pop-to-esi
19305     5b/pop-to-ebx
19306     5a/pop-to-edx
19307     59/pop-to-ecx
19308     58/pop-to-eax
19309     # . epilogue
19310     89/<- %esp 5/r32/ebp
19311     5d/pop-to-ebp
19312     c3/return
19313 
19314 $lookup-var-helper:error1:
19315     (write-buffered *(ebp+0x18) "fn ")
19316     8b/-> *(ebp+0x14) 0/r32/eax
19317     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19318     (write-buffered *(ebp+0x18) %eax)
19319     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
19320     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19321     (write-buffered *(ebp+0x18) "'\n")
19322     (flush *(ebp+0x18))
19323     (stop *(ebp+0x1c) 1)
19324     # never gets here
19325 
19326 $lookup-var-helper:error2:
19327     # eax contains the conflicting var at this point
19328     (write-buffered *(ebp+0x18) "fn ")
19329     50/push-eax
19330     8b/-> *(ebp+0x14) 0/r32/eax
19331     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19332     (write-buffered *(ebp+0x18) %eax)
19333     58/pop-eax
19334     (write-buffered *(ebp+0x18) ": register ")
19335     50/push-eax
19336     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
19337     (write-buffered *(ebp+0x18) %eax)
19338     58/pop-to-eax
19339     (write-buffered *(ebp+0x18) " reads var '")
19340     (write-slice-buffered *(ebp+0x18) *(ebp+8))
19341     (write-buffered *(ebp+0x18) "' after writing var '")
19342     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19343     (write-buffered *(ebp+0x18) %eax)
19344     (write-buffered *(ebp+0x18) "'\n")
19345     (flush *(ebp+0x18))
19346     (stop *(ebp+0x1c) 1)
19347     # never gets here
19348 
19349 dump-vars:  # vars: (addr stack live-var)
19350     # pseudocode:
19351     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19352     #   var min = vars->data
19353     #   while curr >= min
19354     #     var v: (handle var) = *curr
19355     #     print v
19356     #     curr -= 12
19357     #
19358     # . prologue
19359     55/push-ebp
19360     89/<- %ebp 4/r32/esp
19361     # . save registers
19362     52/push-edx
19363     53/push-ebx
19364     56/push-esi
19365     # esi = vars
19366     8b/-> *(ebp+8) 6/r32/esi
19367     # ebx = vars->top
19368     8b/-> *esi 3/r32/ebx
19369     # var min/edx: (addr handle var) = vars->data
19370     8d/copy-address *(esi+8) 2/r32/edx
19371     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
19372     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
19373     {
19374 $dump-vars:loop:
19375       # if (curr < min) return
19376       39/compare %ebx 2/r32/edx
19377       0f 82/jump-if-addr< break/disp32
19378       #
19379       (write-buffered Stderr "  var@")
19380       (dump-var 2 %ebx)
19381       # curr -= 12
19382       81 5/subop/subtract %ebx 0xc/imm32
19383       e9/jump loop/disp32
19384     }
19385 $dump-vars:end:
19386     # . restore registers
19387     5e/pop-to-esi
19388     5b/pop-to-ebx
19389     5a/pop-to-edx
19390     # . epilogue
19391     89/<- %esp 5/r32/ebp
19392     5d/pop-to-ebp
19393     c3/return
19394 
19395 == data
19396 # Like Registers, but no esp or ebp
19397 Mu-registers:  # (addr stream {(handle array byte), int})
19398   # a table is a stream
19399   0xa8/imm32/write
19400   0/imm32/read
19401   0xa8/imm32/length
19402   # data
19403   # general-purpose registers
19404   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
19405   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19406   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19407   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19408   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19409   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19410   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19411   # floating-point registers
19412   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
19413   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
19414   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
19415   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
19416   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
19417   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
19418   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
19419   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
19420 
19421 # Like Mu-registers, but with unique codes for integer and floating-point
19422 # registers.
19423 # Don't use this for code-generation, only for checking.
19424 Mu-registers-unique:  # (addr stream {(handle array byte), int})
19425   # a table is a stream
19426   0xa8/imm32/write
19427   0/imm32/read
19428   0xa8/imm32/length
19429   # data
19430   # general-purpose registers
19431   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
19432   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
19433   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
19434   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
19435   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
19436   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
19437   # floating-point registers
19438   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
19439   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
19440   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
19441   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
19442   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
19443   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
19444   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
19445   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
19446 
19447 $Mu-register-eax:
19448   0x11/imm32/alloc-id
19449   3/imm32/size
19450   0x65/e 0x61/a 0x78/x
19451 
19452 $Mu-register-ecx:
19453   0x11/imm32/alloc-id
19454   3/imm32/size
19455   0x65/e 0x63/c 0x78/x
19456 
19457 $Mu-register-edx:
19458   0x11/imm32/alloc-id
19459   3/imm32/size
19460   0x65/e 0x64/d 0x78/x
19461 
19462 $Mu-register-ebx:
19463   0x11/imm32/alloc-id
19464   3/imm32/size
19465   0x65/e 0x62/b 0x78/x
19466 
19467 $Mu-register-esi:
19468   0x11/imm32/alloc-id
19469   3/imm32/size
19470   0x65/e 0x73/s 0x69/i
19471 
19472 $Mu-register-edi:
19473   0x11/imm32/alloc-id
19474   3/imm32/size
19475   0x65/e 0x64/d 0x69/i
19476 
19477 $Mu-register-xmm0:
19478   0x11/imm32/alloc-id:fake:payload
19479   # "xmm0"
19480   0x4/imm32/size
19481   0x78/x 0x6d/m 0x6d/m 0x30/0
19482 
19483 $Mu-register-xmm1:
19484   0x11/imm32/alloc-id:fake:payload
19485   # "xmm1"
19486   0x4/imm32/size
19487   0x78/x 0x6d/m 0x6d/m 0x31/1
19488 
19489 $Mu-register-xmm2:
19490   0x11/imm32/alloc-id:fake:payload
19491   # "xmm2"
19492   0x4/imm32/size
19493   0x78/x 0x6d/m 0x6d/m 0x32/2
19494 
19495 $Mu-register-xmm3:
19496   0x11/imm32/alloc-id:fake:payload
19497   # "xmm3"
19498   0x4/imm32/size
19499   0x78/x 0x6d/m 0x6d/m 0x33/3
19500 
19501 $Mu-register-xmm4:
19502   0x11/imm32/alloc-id:fake:payload
19503   # "xmm4"
19504   0x4/imm32/size
19505   0x78/x 0x6d/m 0x6d/m 0x34/4
19506 
19507 $Mu-register-xmm5:
19508   0x11/imm32/alloc-id:fake:payload
19509   # "xmm5"
19510   0x4/imm32/size
19511   0x78/x 0x6d/m 0x6d/m 0x35/5
19512 
19513 $Mu-register-xmm6:
19514   0x11/imm32/alloc-id:fake:payload
19515   # "xmm6"
19516   0x4/imm32/size
19517   0x78/x 0x6d/m 0x6d/m 0x36/6
19518 
19519 $Mu-register-xmm7:
19520   0x11/imm32/alloc-id:fake:payload
19521   # "xmm7"
19522   0x4/imm32/size
19523   0x78/x 0x6d/m 0x6d/m 0x37/7
19524 
19525 == code
19526 
19527 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
19528 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
19529     # . prologue
19530     55/push-ebp
19531     89/<- %ebp 4/r32/esp
19532     # . save registers
19533     50/push-eax
19534     # var out-addr/eax: (addr var)
19535     (lookup *(ebp+8) *(ebp+0xc))  # => eax
19536     #
19537     (binding-exists? %eax *(ebp+0x10))  # => eax
19538     3d/compare-eax-and 0/imm32/false
19539     75/jump-if-!= $maybe-define-var:end/disp8
19540     # otherwise update vars
19541     (push *(ebp+0x10) *(ebp+8))
19542     (push *(ebp+0x10) *(ebp+0xc))
19543     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
19544 $maybe-define-var:end:
19545     # . restore registers
19546     58/pop-to-eax
19547     # . epilogue
19548     89/<- %esp 5/r32/ebp
19549     5d/pop-to-ebp
19550     c3/return
19551 
19552 # simpler version of lookup-var-helper
19553 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
19554     # pseudocode:
19555     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
19556     #   var min = vars->data
19557     #   while curr >= min
19558     #     var v: (handle var) = *curr
19559     #     if v->name == target->name
19560     #       return true
19561     #     curr -= 12
19562     #   return false
19563     #
19564     # . prologue
19565     55/push-ebp
19566     89/<- %ebp 4/r32/esp
19567     # . save registers
19568     51/push-ecx
19569     52/push-edx
19570     56/push-esi
19571     # var target-name/ecx: (addr array byte) = lookup(target->name)
19572     8b/-> *(ebp+8) 0/r32/eax
19573     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19574     89/<- %ecx 0/r32/eax
19575     # esi = vars
19576     8b/-> *(ebp+0xc) 6/r32/esi
19577     # eax = vars->top
19578     8b/-> *esi 0/r32/eax
19579     # var min/edx: (addr handle var) = vars->data
19580     8d/copy-address *(esi+8) 2/r32/edx
19581     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
19582     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
19583     {
19584 $binding-exists?:loop:
19585       # if (curr < min) return
19586       39/compare %esi 2/r32/edx
19587       0f 82/jump-if-addr< break/disp32
19588       # var v/eax: (addr var) = lookup(*curr)
19589       (lookup *esi *(esi+4))  # => eax
19590       # var vn/eax: (addr array byte) = lookup(v->name)
19591       (lookup *eax *(eax+4))  # Var-name Var-name => eax
19592       # if (vn == target-name) return true
19593       (string-equal? %ecx %eax)  # => eax
19594       3d/compare-eax-and 0/imm32/false
19595       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
19596       # curr -= 12
19597       81 5/subop/subtract %esi 0xc/imm32
19598       e9/jump loop/disp32
19599     }
19600     b8/copy-to-eax 0/imm32/false
19601 $binding-exists?:end:
19602     # . restore registers
19603     5e/pop-to-esi
19604     5a/pop-to-edx
19605     59/pop-to-ecx
19606     # . epilogue
19607     89/<- %esp 5/r32/ebp
19608     5d/pop-to-ebp
19609     c3/return
19610 
19611 test-parse-mu-stmt:
19612     # . prologue
19613     55/push-ebp
19614     89/<- %ebp 4/r32/esp
19615     # setup
19616     8b/-> *Primitive-type-ids 0/r32/eax
19617     89/<- *Type-id 0/r32/eax  # stream-write
19618     (clear-stream _test-input-stream)
19619     (write _test-input-stream "increment n\n")
19620     # var vars/ecx: (stack (addr var) 16)
19621     81 5/subop/subtract %esp 0xc0/imm32
19622     68/push 0xc0/imm32/size
19623     68/push 0/imm32/top
19624     89/<- %ecx 4/r32/esp
19625     (clear-stack %ecx)
19626     # var v/edx: (handle var)
19627     68/push 0/imm32
19628     68/push 0/imm32
19629     89/<- %edx 4/r32/esp
19630     # var s/eax: (handle array byte)
19631     68/push 0/imm32
19632     68/push 0/imm32
19633     89/<- %eax 4/r32/esp
19634     # v = new var("n")
19635     (copy-array Heap "n" %eax)
19636     (new-var Heap *eax *(eax+4) %edx)
19637     #
19638     (push %ecx *edx)
19639     (push %ecx *(edx+4))
19640     (push %ecx 0)
19641     # var out/eax: (handle stmt)
19642     68/push 0/imm32
19643     68/push 0/imm32
19644     89/<- %eax 4/r32/esp
19645     # convert
19646     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19647     # var out-addr/edx: (addr stmt) = lookup(*out)
19648     (lookup *eax *(eax+4))  # => eax
19649     89/<- %edx 0/r32/eax
19650     # out->tag
19651     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
19652     # out->operation
19653     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19654     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
19655     # out->inouts->value->name
19656     # . eax = out->inouts
19657     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19658     # . eax = out->inouts->value
19659     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19660     # . eax = out->inouts->value->name
19661     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19662     # .
19663     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
19664     # . epilogue
19665     89/<- %esp 5/r32/ebp
19666     5d/pop-to-ebp
19667     c3/return
19668 
19669 test-parse-mu-stmt-with-comma:
19670     # . prologue
19671     55/push-ebp
19672     89/<- %ebp 4/r32/esp
19673     # setup
19674     8b/-> *Primitive-type-ids 0/r32/eax
19675     89/<- *Type-id 0/r32/eax  # stream-write
19676     (clear-stream _test-input-stream)
19677     (write _test-input-stream "copy-to n, 3\n")
19678     # var vars/ecx: (stack (addr var) 16)
19679     81 5/subop/subtract %esp 0xc0/imm32
19680     68/push 0xc0/imm32/size
19681     68/push 0/imm32/top
19682     89/<- %ecx 4/r32/esp
19683     (clear-stack %ecx)
19684     # var v/edx: (handle var)
19685     68/push 0/imm32
19686     68/push 0/imm32
19687     89/<- %edx 4/r32/esp
19688     # var s/eax: (handle array byte)
19689     68/push 0/imm32
19690     68/push 0/imm32
19691     89/<- %eax 4/r32/esp
19692     # v = new var("n")
19693     (copy-array Heap "n" %eax)
19694     (new-var Heap *eax *(eax+4) %edx)
19695     #
19696     (push %ecx *edx)
19697     (push %ecx *(edx+4))
19698     (push %ecx 0)
19699     # var out/eax: (handle stmt)
19700     68/push 0/imm32
19701     68/push 0/imm32
19702     89/<- %eax 4/r32/esp
19703     # convert
19704     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
19705     # var out-addr/edx: (addr stmt) = lookup(*out)
19706     (lookup *eax *(eax+4))  # => eax
19707     89/<- %edx 0/r32/eax
19708     # out->tag
19709     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
19710     # out->operation
19711     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
19712     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
19713     # out->inouts->value->name
19714     # . eax = out->inouts
19715     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
19716     # . eax = out->inouts->value
19717     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
19718     # . eax = out->inouts->value->name
19719     (lookup *eax *(eax+4))  # Var-name Var-name => eax
19720     # .
19721     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
19722     # . epilogue
19723     89/<- %esp 5/r32/ebp
19724     5d/pop-to-ebp
19725     c3/return
19726 
19727 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
19728     # . prologue
19729     55/push-ebp
19730     89/<- %ebp 4/r32/esp
19731     # . save registers
19732     50/push-eax
19733     51/push-ecx
19734     # ecx = out
19735     8b/-> *(ebp+0x14) 1/r32/ecx
19736     #
19737     (allocate *(ebp+8) *Var-size %ecx)
19738     # var out-addr/eax: (addr var)
19739     (lookup *ecx *(ecx+4))  # => eax
19740     # out-addr->name = name
19741     8b/-> *(ebp+0xc) 1/r32/ecx
19742     89/<- *eax 1/r32/ecx  # Var-name
19743     8b/-> *(ebp+0x10) 1/r32/ecx
19744     89/<- *(eax+4) 1/r32/ecx  # Var-name
19745 #?     (write-buffered Stderr "var ")
19746 #?     (lookup *(ebp+0xc) *(ebp+0x10))
19747 #?     (write-buffered Stderr %eax)
19748 #?     (write-buffered Stderr " at ")
19749 #?     8b/-> *(ebp+0x14) 1/r32/ecx
19750 #?     (lookup *ecx *(ecx+4))  # => eax
19751 #?     (write-int32-hex-buffered Stderr %eax)
19752 #?     (write-buffered Stderr Newline)
19753 #?     (flush Stderr)
19754 $new-var:end:
19755     # . restore registers
19756     59/pop-to-ecx
19757     58/pop-to-eax
19758     # . epilogue
19759     89/<- %esp 5/r32/ebp
19760     5d/pop-to-ebp
19761     c3/return
19762 
19763 # WARNING: modifies name
19764 new-literal-integer:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19765     # . prologue
19766     55/push-ebp
19767     89/<- %ebp 4/r32/esp
19768     # . save registers
19769     50/push-eax
19770     51/push-ecx
19771     # first strip out metadata
19772     8b/-> *(ebp+0xc) 1/r32/ecx
19773     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
19774     # if (!is-hex-int?(name)) abort
19775     (hex-int? *(ebp+0xc))  # => eax
19776     3d/compare-eax-and 0/imm32/false
19777     0f 84/jump-if-= $new-literal-integer:abort/disp32
19778     # a little more error-checking
19779     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
19780     # out = new var(s)
19781     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19782     # var out-addr/ecx: (addr var) = lookup(*out)
19783     8b/-> *(ebp+0x10) 0/r32/eax
19784     (lookup *eax *(eax+4))  # => eax
19785     89/<- %ecx 0/r32/eax
19786     # out-addr->block-depth = *Curr-block-depth
19787     8b/-> *Curr-block-depth 0/r32/eax
19788     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19789     # out-addr->type = new tree()
19790     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19791     (allocate *(ebp+8) *Type-tree-size %eax)
19792     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19793     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19794     # nothing else to do; default type is 'literal'
19795 $new-literal-integer:end:
19796     # . reclaim locals
19797     81 0/subop/add %esp 8/imm32
19798     # . restore registers
19799     59/pop-to-ecx
19800     58/pop-to-eax
19801     # . epilogue
19802     89/<- %esp 5/r32/ebp
19803     5d/pop-to-ebp
19804     c3/return
19805 
19806 $new-literal-integer:abort:
19807     (write-buffered *(ebp+0x18) "fn ")
19808     8b/-> *(ebp+0x14) 0/r32/eax
19809     (lookup *eax *(eax+4))  # Function-name Function-name => eax
19810     (write-buffered *(ebp+0x18) %eax)
19811     (write-buffered *(ebp+0x18) ": variable '")
19812     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
19813     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
19814     (flush *(ebp+0x18))
19815     (stop *(ebp+0x1c) 1)
19816     # never gets here
19817 
19818 # precondition: name is a valid hex integer; require a '0x' prefix
19819 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
19820     # . prologue
19821     55/push-ebp
19822     89/<- %ebp 4/r32/esp
19823     # . save registers
19824     50/push-eax
19825     51/push-ecx
19826     52/push-edx
19827     # ecx = name
19828     8b/-> *(ebp+8) 1/r32/ecx
19829     # var start/edx: (addr byte) = name->start
19830     8b/-> *ecx 2/r32/edx
19831     # if (*start == '-') ++start
19832     b8/copy-to-eax 0/imm32
19833     8a/copy-byte *edx 0/r32/AL
19834     3d/compare-eax-and 0x2d/imm32/dash
19835     {
19836       75/jump-if-!= break/disp8
19837       42/increment-edx
19838     }
19839     # var end/ecx: (addr byte) = name->end
19840     8b/-> *(ecx+4) 1/r32/ecx
19841     # var len/eax: int = name->end - name->start
19842     89/<- %eax 1/r32/ecx
19843     29/subtract-from %eax 2/r32/edx
19844     # if (len <= 1) return
19845     3d/compare-eax-with 1/imm32
19846     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
19847 $check-mu-hex-int:length->-1:
19848     # if slice-starts-with?({start, end}, "0x") return
19849     # . var tmp = {start, end}
19850     51/push-ecx
19851     52/push-edx
19852     89/<- %eax 4/r32/esp
19853     # .
19854     (slice-starts-with? %eax "0x")  # => eax
19855     # . reclaim tmp
19856     81 0/subop/add %esp 8/imm32
19857     # .
19858     3d/compare-eax-with 0/imm32/false
19859     75/jump-if-!= $check-mu-hex-int:end/disp8
19860 $check-mu-hex-int:abort:
19861     # otherwise abort
19862     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
19863     (write-slice-buffered *(ebp+0xc) *(ebp+8))
19864     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
19865     (flush *(ebp+0xc))
19866     (stop *(ebp+0x10) 1)
19867 $check-mu-hex-int:end:
19868     # . restore registers
19869     5a/pop-to-edx
19870     59/pop-to-ecx
19871     58/pop-to-eax
19872     # . epilogue
19873     89/<- %esp 5/r32/ebp
19874     5d/pop-to-ebp
19875     c3/return
19876 
19877 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19878     # . prologue
19879     55/push-ebp
19880     89/<- %ebp 4/r32/esp
19881     # . save registers
19882     50/push-eax
19883     51/push-ecx
19884     # var s/ecx: (handle array byte)
19885     68/push 0/imm32
19886     68/push 0/imm32
19887     89/<- %ecx 4/r32/esp
19888     # s = slice-to-string(name)
19889     (slice-to-string Heap *(ebp+0xc) %ecx)
19890     # allocate to out
19891     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19892     # var out-addr/ecx: (addr var) = lookup(*out)
19893     8b/-> *(ebp+0x10) 1/r32/ecx
19894     (lookup *ecx *(ecx+4))  # => eax
19895     89/<- %ecx 0/r32/eax
19896     # out-addr->block-depth = *Curr-block-depth
19897     8b/-> *Curr-block-depth 0/r32/eax
19898     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19899     # out-addr->type/eax = new type
19900     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19901     (allocate *(ebp+8) *Type-tree-size %eax)
19902     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19903     # nothing else to do; default type is 'literal'
19904     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19905 $new-literal:end:
19906     # . reclaim locals
19907     81 0/subop/add %esp 8/imm32
19908     # . restore registers
19909     59/pop-to-ecx
19910     58/pop-to-eax
19911     # . epilogue
19912     89/<- %esp 5/r32/ebp
19913     5d/pop-to-ebp
19914     c3/return
19915 
19916 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19917     # . prologue
19918     55/push-ebp
19919     89/<- %ebp 4/r32/esp
19920     # . save registers
19921     50/push-eax
19922     51/push-ecx
19923     # var s/ecx: (handle array byte)
19924     68/push 0/imm32
19925     68/push 0/imm32
19926     89/<- %ecx 4/r32/esp
19927     # s = slice-to-string(name)
19928     (slice-to-string Heap *(ebp+0xc) %ecx)
19929     # allocate to out
19930     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19931     # var out-addr/ecx: (addr var) = lookup(*out)
19932     8b/-> *(ebp+0x10) 1/r32/ecx
19933     (lookup *ecx *(ecx+4))  # => eax
19934     89/<- %ecx 0/r32/eax
19935     # out-addr->block-depth = *Curr-block-depth
19936     8b/-> *Curr-block-depth 0/r32/eax
19937     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
19938     # out-addr->type/eax = new type
19939     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
19940     (allocate *(ebp+8) *Type-tree-size %eax)
19941     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19942     # out-addr->type->value = literal-string
19943     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
19944     # out-addr->type->is-atom? = true
19945     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
19946 $new-literal-string:end:
19947     # . reclaim locals
19948     81 0/subop/add %esp 8/imm32
19949     # . restore registers
19950     59/pop-to-ecx
19951     58/pop-to-eax
19952     # . epilogue
19953     89/<- %esp 5/r32/ebp
19954     5d/pop-to-ebp
19955     c3/return
19956 
19957 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
19958     # . prologue
19959     55/push-ebp
19960     89/<- %ebp 4/r32/esp
19961     # . save registers
19962     51/push-ecx
19963     # var tmp/ecx: (handle array byte)
19964     68/push 0/imm32
19965     68/push 0/imm32
19966     89/<- %ecx 4/r32/esp
19967     # tmp = slice-to-string(name)
19968     (slice-to-string Heap *(ebp+0xc) %ecx)
19969     # out = new-var(tmp)
19970     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
19971 $new-var-from-slice:end:
19972     # . reclaim locals
19973     81 0/subop/add %esp 8/imm32
19974     # . restore registers
19975     59/pop-to-ecx
19976     # . epilogue
19977     89/<- %esp 5/r32/ebp
19978     5d/pop-to-ebp
19979     c3/return
19980 
19981 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
19982     # . prologue
19983     55/push-ebp
19984     89/<- %ebp 4/r32/esp
19985     # . save registers
19986     50/push-eax
19987     51/push-ecx
19988     #
19989     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
19990     # var out-addr/eax: (addr stmt) = lookup(*out)
19991     8b/-> *(ebp+0x14) 0/r32/eax
19992     (lookup *eax *(eax+4))  # => eax
19993     # out-addr->tag = stmt
19994     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
19995     # result->var = var
19996     8b/-> *(ebp+0xc) 1/r32/ecx
19997     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
19998     8b/-> *(ebp+0x10) 1/r32/ecx
19999     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
20000 $new-var-def:end:
20001     # . restore registers
20002     59/pop-to-ecx
20003     58/pop-to-eax
20004     # . epilogue
20005     89/<- %esp 5/r32/ebp
20006     5d/pop-to-ebp
20007     c3/return
20008 
20009 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
20010     # . prologue
20011     55/push-ebp
20012     89/<- %ebp 4/r32/esp
20013     # . save registers
20014     50/push-eax
20015     # eax = out
20016     8b/-> *(ebp+0x14) 0/r32/eax
20017     #
20018     (allocate *(ebp+8) *Stmt-size %eax)
20019     # var out-addr/eax: (addr stmt) = lookup(*out)
20020     (lookup *eax *(eax+4))  # => eax
20021     # set tag
20022     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
20023     # set output
20024     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
20025     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
20026 $new-reg-var-def:end:
20027     # . restore registers
20028     58/pop-to-eax
20029     # . epilogue
20030     89/<- %esp 5/r32/ebp
20031     5d/pop-to-ebp
20032     c3/return
20033 
20034 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
20035     # . prologue
20036     55/push-ebp
20037     89/<- %ebp 4/r32/esp
20038     # . save registers
20039     50/push-eax
20040     51/push-ecx
20041     57/push-edi
20042     # edi = out
20043     8b/-> *(ebp+0x1c) 7/r32/edi
20044     # *out = new list
20045     (allocate *(ebp+8) *List-size %edi)
20046     # var out-addr/edi: (addr list _type) = lookup(*out)
20047     (lookup *edi *(edi+4))  # => eax
20048     89/<- %edi 0/r32/eax
20049     # out-addr->value = value
20050     8b/-> *(ebp+0xc) 0/r32/eax
20051     89/<- *edi 0/r32/eax  # List-value
20052     8b/-> *(ebp+0x10) 0/r32/eax
20053     89/<- *(edi+4) 0/r32/eax  # List-value
20054     # if (list == null) return
20055     81 7/subop/compare *(ebp+0x14) 0/imm32
20056     74/jump-if-= $append-list:end/disp8
20057     # otherwise append
20058 $append-list:non-empty-list:
20059     # var curr/eax: (addr list _type) = lookup(list)
20060     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20061     # while (curr->next != null) curr = curr->next
20062     {
20063       81 7/subop/compare *(eax+8) 0/imm32  # List-next
20064       74/jump-if-= break/disp8
20065       # curr = lookup(curr->next)
20066       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
20067       #
20068       eb/jump loop/disp8
20069     }
20070     # edi = out
20071     8b/-> *(ebp+0x1c) 7/r32/edi
20072     # curr->next = out
20073     8b/-> *edi 1/r32/ecx
20074     89/<- *(eax+8) 1/r32/ecx  # List-next
20075     8b/-> *(edi+4) 1/r32/ecx
20076     89/<- *(eax+0xc) 1/r32/ecx  # List-next
20077     # out = list
20078     8b/-> *(ebp+0x14) 1/r32/ecx
20079     89/<- *edi 1/r32/ecx
20080     8b/-> *(ebp+0x18) 1/r32/ecx
20081     89/<- *(edi+4) 1/r32/ecx
20082 $append-list:end:
20083     # . restore registers
20084     5f/pop-to-edi
20085     59/pop-to-ecx
20086     58/pop-to-eax
20087     # . epilogue
20088     89/<- %esp 5/r32/ebp
20089     5d/pop-to-ebp
20090     c3/return
20091 
20092 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
20093     # . prologue
20094     55/push-ebp
20095     89/<- %ebp 4/r32/esp
20096     # . save registers
20097     50/push-eax
20098     51/push-ecx
20099     57/push-edi
20100     # edi = out
20101     8b/-> *(ebp+0x20) 7/r32/edi
20102     # out = new stmt-var
20103     (allocate *(ebp+8) *Stmt-var-size %edi)
20104     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
20105     (lookup *edi *(edi+4))  # => eax
20106     89/<- %ecx 0/r32/eax
20107     # out-addr->value = v
20108     8b/-> *(ebp+0xc) 0/r32/eax
20109     89/<- *ecx 0/r32/eax  # Stmt-var-value
20110     8b/-> *(ebp+0x10) 0/r32/eax
20111     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
20112     # out-addr->is-deref? = is-deref?
20113     8b/-> *(ebp+0x1c) 0/r32/eax
20114     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
20115     # if (vars == null) return result
20116     81 7/subop/compare *(ebp+0x14) 0/imm32/null
20117     74/jump-if-= $append-stmt-var:end/disp8
20118     # otherwise append
20119     # var curr/eax: (addr stmt-var) = lookup(vars)
20120     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
20121     # while (curr->next != null) curr = curr->next
20122     {
20123       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20124       74/jump-if-= break/disp8
20125       # curr = lookup(curr->next)
20126       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
20127       #
20128       eb/jump loop/disp8
20129     }
20130     # curr->next = out
20131     8b/-> *edi 1/r32/ecx
20132     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
20133     8b/-> *(edi+4) 1/r32/ecx
20134     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
20135     # out = vars
20136     8b/-> *(ebp+0x14) 1/r32/ecx
20137     89/<- *edi 1/r32/ecx
20138     8b/-> *(ebp+0x18) 1/r32/ecx
20139     89/<- *(edi+4) 1/r32/ecx
20140 $append-stmt-var:end:
20141     # . restore registers
20142     5f/pop-to-edi
20143     59/pop-to-ecx
20144     58/pop-to-eax
20145     # . epilogue
20146     89/<- %esp 5/r32/ebp
20147     5d/pop-to-ebp
20148     c3/return
20149 
20150 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
20151     # . prologue
20152     55/push-ebp
20153     89/<- %ebp 4/r32/esp
20154     # . save registers
20155     50/push-eax
20156     56/push-esi
20157     # esi = block
20158     8b/-> *(ebp+0xc) 6/r32/esi
20159     # block->stmts = append(x, block->stmts)
20160     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
20161     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
20162 $append-to-block:end:
20163     # . restore registers
20164     5e/pop-to-esi
20165     58/pop-to-eax
20166     # . epilogue
20167     89/<- %esp 5/r32/ebp
20168     5d/pop-to-ebp
20169     c3/return
20170 
20171 ## Parsing types
20172 # We need to create metadata on user-defined types, and we need to use this
20173 # metadata as we parse instructions.
20174 # However, we also want to allow types to be used before their definitions.
20175 # This means we can't ever assume any type data structures exist.
20176 
20177 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
20178     # . prologue
20179     55/push-ebp
20180     89/<- %ebp 4/r32/esp
20181     # . save registers
20182     50/push-eax
20183     56/push-esi
20184     # var container-type/esi: type-id
20185     (container-type *(ebp+8))  # => eax
20186     89/<- %esi 0/r32/eax
20187     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
20188     68/push 0/imm32
20189     68/push 0/imm32
20190     89/<- %eax 4/r32/esp
20191     (find-or-create-typeinfo %esi %eax)
20192     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
20193     (lookup *eax *(eax+4))  # => eax
20194     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
20195 #?     (write-buffered Stderr "constant: ")
20196 #?     (write-slice-buffered Stderr *(ebp+0xc))
20197 #?     (write-buffered Stderr Newline)
20198 #?     (flush Stderr)
20199     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
20200 #?     8b/-> *(ebp+0x10) 0/r32/eax
20201 #?     (write-buffered Stderr "@")
20202 #?     (lookup *eax *(eax+4))
20203 #?     (write-int32-hex-buffered Stderr %eax)
20204 #?     (lookup *eax *(eax+4))
20205 #?     (write-buffered Stderr %eax)
20206 #?     (write-buffered Stderr Newline)
20207 #?     (flush Stderr)
20208 #?     (write-buffered Stderr "offset: ")
20209 #?     8b/-> *(eax+0x14) 0/r32/eax
20210 #?     (write-int32-hex-buffered Stderr %eax)
20211 #?     (write-buffered Stderr Newline)
20212 #?     (flush Stderr)
20213 $lookup-or-create-constant:end:
20214     # . reclaim locals
20215     81 0/subop/add %esp 8/imm32
20216     # . restore registers
20217     5e/pop-to-esi
20218     58/pop-to-eax
20219     # . epilogue
20220     89/<- %esp 5/r32/ebp
20221     5d/pop-to-ebp
20222     c3/return
20223 
20224 # if addr var:
20225 #   container->var->type->right->left->value
20226 # otherwise
20227 #   container->var->type->value
20228 container-type:  # container: (addr stmt-var) -> result/eax: type-id
20229     # . prologue
20230     55/push-ebp
20231     89/<- %ebp 4/r32/esp
20232     #
20233     8b/-> *(ebp+8) 0/r32/eax
20234     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20235     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20236     {
20237       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
20238       74/jump-if-= break/disp8
20239       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
20240       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20241     }
20242     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
20243 $container-type:end:
20244     # . epilogue
20245     89/<- %esp 5/r32/ebp
20246     5d/pop-to-ebp
20247     c3/return
20248 
20249 container?:  # t: type-id -> result/eax: boolean
20250     # . prologue
20251     55/push-ebp
20252     89/<- %ebp 4/r32/esp
20253     #
20254     8b/-> *(ebp+8) 0/r32/eax
20255     c1/shift 4/subop/left %eax 2/imm8
20256     3b/compare 0/r32/eax *Primitive-type-ids
20257     0f 9d/set-if->= %al
20258     25/and-eax-with 0xff/imm32
20259 $container?:end:
20260     # . epilogue
20261     89/<- %esp 5/r32/ebp
20262     5d/pop-to-ebp
20263     c3/return
20264 
20265 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20266     # . prologue
20267     55/push-ebp
20268     89/<- %ebp 4/r32/esp
20269     # . save registers
20270     50/push-eax
20271     51/push-ecx
20272     52/push-edx
20273     57/push-edi
20274     # edi = out
20275     8b/-> *(ebp+0xc) 7/r32/edi
20276     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
20277     68/push 0/imm32
20278     68/push 0/imm32
20279     89/<- %ecx 4/r32/esp
20280     # find-typeinfo(t, out)
20281     (find-typeinfo *(ebp+8) %edi)
20282     {
20283       # if (*out != 0) break
20284       81 7/subop/compare *edi 0/imm32
20285       0f 85/jump-if-!= break/disp32
20286 $find-or-create-typeinfo:create:
20287       # *out = allocate
20288       (allocate Heap *Typeinfo-size %edi)
20289       # var tmp/eax: (addr typeinfo) = lookup(*out)
20290       (lookup *edi *(edi+4))  # => eax
20291 #?     (write-buffered Stderr "created typeinfo at ")
20292 #?     (write-int32-hex-buffered Stderr %eax)
20293 #?     (write-buffered Stderr " for type-id ")
20294 #?     (write-int32-hex-buffered Stderr *(ebp+8))
20295 #?     (write-buffered Stderr Newline)
20296 #?     (flush Stderr)
20297       # tmp->id = t
20298       8b/-> *(ebp+8) 2/r32/edx
20299       89/<- *eax 2/r32/edx  # Typeinfo-id
20300       # tmp->fields = new table
20301       # . fields = new table
20302       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
20303       # . tmp->fields = fields
20304       8b/-> *ecx 2/r32/edx
20305       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
20306       8b/-> *(ecx+4) 2/r32/edx
20307       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
20308       # tmp->next = Program->types
20309       8b/-> *_Program-types 1/r32/ecx
20310       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
20311       8b/-> *_Program-types->payload 1/r32/ecx
20312       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
20313       # Program->types = out
20314       8b/-> *edi 1/r32/ecx
20315       89/<- *_Program-types 1/r32/ecx
20316       8b/-> *(edi+4) 1/r32/ecx
20317       89/<- *_Program-types->payload 1/r32/ecx
20318     }
20319 $find-or-create-typeinfo:end:
20320     # . reclaim locals
20321     81 0/subop/add %esp 8/imm32
20322     # . restore registers
20323     5f/pop-to-edi
20324     5a/pop-to-edx
20325     59/pop-to-ecx
20326     58/pop-to-eax
20327     # . epilogue
20328     89/<- %esp 5/r32/ebp
20329     5d/pop-to-ebp
20330     c3/return
20331 
20332 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
20333     # . prologue
20334     55/push-ebp
20335     89/<- %ebp 4/r32/esp
20336     # . save registers
20337     50/push-eax
20338     51/push-ecx
20339     52/push-edx
20340     57/push-edi
20341     # ecx = t
20342     8b/-> *(ebp+8) 1/r32/ecx
20343     # edi = out
20344     8b/-> *(ebp+0xc) 7/r32/edi
20345     # *out = Program->types
20346     8b/-> *_Program-types 0/r32/eax
20347     89/<- *edi 0/r32/eax
20348     8b/-> *_Program-types->payload 0/r32/eax
20349     89/<- *(edi+4) 0/r32/eax
20350     {
20351 $find-typeinfo:loop:
20352       # if (*out == 0) break
20353       81 7/subop/compare *edi 0/imm32
20354       74/jump-if-= break/disp8
20355 $find-typeinfo:check:
20356       # var tmp/eax: (addr typeinfo) = lookup(*out)
20357       (lookup *edi *(edi+4))  # => eax
20358       # if (tmp->id == t) break
20359       39/compare *eax 1/r32/ecx  # Typeinfo-id
20360       74/jump-if-= break/disp8
20361 $find-typeinfo:continue:
20362       # *out = tmp->next
20363       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
20364       89/<- *edi 2/r32/edx
20365       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
20366       89/<- *(edi+4) 2/r32/edx
20367       #
20368       eb/jump loop/disp8
20369     }
20370 $find-typeinfo:end:
20371     # . restore registers
20372     5f/pop-to-edi
20373     5a/pop-to-edx
20374     59/pop-to-ecx
20375     58/pop-to-eax
20376     # . epilogue
20377     89/<- %esp 5/r32/ebp
20378     5d/pop-to-ebp
20379     c3/return
20380 
20381 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
20382     # . prologue
20383     55/push-ebp
20384     89/<- %ebp 4/r32/esp
20385     # . save registers
20386     50/push-eax
20387     52/push-edx
20388     57/push-edi
20389     # var dest/edi: (handle typeinfo-entry)
20390     68/push 0/imm32
20391     68/push 0/imm32
20392     89/<- %edi 4/r32/esp
20393     # find-or-create-typeinfo-fields(T, f, dest)
20394     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
20395     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
20396     (lookup *edi *(edi+4))  # => eax
20397     89/<- %edi 0/r32/eax
20398     # if dest-addr->output-var doesn't exist, create it
20399     {
20400       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
20401       0f 85/jump-if-!= break/disp32
20402       # dest-addr->output-var = new var(dummy name, type, -1 offset)
20403       # . var name/eax: (handle array byte) = "field"
20404       68/push 0/imm32
20405       68/push 0/imm32
20406       89/<- %eax 4/r32/esp
20407       (slice-to-string Heap *(ebp+0xc) %eax)
20408       # . new var
20409       8d/copy-address *(edi+0xc) 2/r32/edx
20410       (new-var Heap  *eax *(eax+4)  %edx)
20411       # . reclaim name
20412       81 0/subop/add %esp 8/imm32
20413       # var result/edx: (addr var) = lookup(dest-addr->output-var)
20414       (lookup *(edi+0xc) *(edi+0x10))  # => eax
20415       89/<- %edx 0/r32/eax
20416       # result->type = new constant type
20417       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
20418       (allocate Heap *Type-tree-size %eax)
20419       (lookup *(edx+8) *(edx+0xc))  # => eax
20420       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
20421       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
20422       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
20423       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
20424       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
20425       # result->offset isn't filled out yet
20426       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
20427     }
20428     # out = dest-addr->output-var
20429     8b/-> *(ebp+0x10) 2/r32/edx
20430     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20431     89/<- *edx 0/r32/eax
20432     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
20433     89/<- *(edx+4) 0/r32/eax
20434 $find-or-create-typeinfo-output-var:end:
20435     # . reclaim locals
20436     81 0/subop/add %esp 8/imm32
20437     # . restore registers
20438     5f/pop-to-edi
20439     5a/pop-to-edx
20440     58/pop-to-eax
20441     # . epilogue
20442     89/<- %esp 5/r32/ebp
20443     5d/pop-to-ebp
20444     c3/return
20445 
20446 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
20447     # . prologue
20448     55/push-ebp
20449     89/<- %ebp 4/r32/esp
20450     # . save registers
20451     50/push-eax
20452     56/push-esi
20453     57/push-edi
20454     # eax = lookup(T->fields)
20455     8b/-> *(ebp+8) 0/r32/eax
20456     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
20457     # edi = out
20458     8b/-> *(ebp+0x10) 7/r32/edi
20459     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
20460     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
20461     89/<- %esi 0/r32/eax
20462     # if src doesn't exist, allocate it
20463     {
20464       81 7/subop/compare *esi 0/imm32
20465       75/jump-if-!= break/disp8
20466       (allocate Heap *Typeinfo-entry-size %esi)
20467 #?       (write-buffered Stderr "handle at ")
20468 #?       (write-int32-hex-buffered Stderr %esi)
20469 #?       (write-buffered Stderr ": ")
20470 #?       (write-int32-hex-buffered Stderr *esi)
20471 #?       (write-buffered Stderr " ")
20472 #?       (write-int32-hex-buffered Stderr *(esi+4))
20473 #?       (write-buffered Stderr Newline)
20474 #?       (flush Stderr)
20475 #?       (lookup *esi *(esi+4))
20476 #?       (write-buffered Stderr "created typeinfo fields at ")
20477 #?       (write-int32-hex-buffered Stderr %esi)
20478 #?       (write-buffered Stderr " for ")
20479 #?       (write-int32-hex-buffered Stderr *(ebp+8))
20480 #?       (write-buffered Stderr Newline)
20481 #?       (flush Stderr)
20482     }
20483     # *out = src
20484     # . *edi = *src
20485     8b/-> *esi 0/r32/eax
20486     89/<- *edi 0/r32/eax
20487     8b/-> *(esi+4) 0/r32/eax
20488     89/<- *(edi+4) 0/r32/eax
20489 $find-or-create-typeinfo-fields:end:
20490     # . restore registers
20491     5f/pop-to-edi
20492     5e/pop-to-esi
20493     58/pop-to-eax
20494     # . epilogue
20495     89/<- %esp 5/r32/ebp
20496     5d/pop-to-ebp
20497     c3/return
20498 
20499 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20500     # pseudocode:
20501     #   var line: (stream byte 512)
20502     #   curr-index = 0
20503     #   while true
20504     #     clear-stream(line)
20505     #     read-line-buffered(in, line)
20506     #     if line->write == 0
20507     #       abort
20508     #     word-slice = next-mu-token(line)
20509     #     if slice-empty?(word-slice)               # end of line
20510     #       continue
20511     #     if slice-equal?(word-slice, "}")
20512     #       break
20513     #     var v: (handle var) = parse-var-with-type(word-slice, line)
20514     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
20515     #     TODO: ensure that r->first is null
20516     #     r->index = curr-index
20517     #     curr-index++
20518     #     r->input-var = v
20519     #     if r->output-var == 0
20520     #       r->output-var = new literal
20521     #     TODO: ensure nothing else in line
20522     # t->total-size-in-bytes = -2 (not yet initialized)
20523     #
20524     # . prologue
20525     55/push-ebp
20526     89/<- %ebp 4/r32/esp
20527     # var curr-index: int at *(ebp-4)
20528     68/push 0/imm32
20529     # . save registers
20530     50/push-eax
20531     51/push-ecx
20532     52/push-edx
20533     53/push-ebx
20534     56/push-esi
20535     57/push-edi
20536     # edi = t
20537     8b/-> *(ebp+0xc) 7/r32/edi
20538     # var line/ecx: (stream byte 512)
20539     81 5/subop/subtract %esp 0x200/imm32
20540     68/push 0x200/imm32/size
20541     68/push 0/imm32/read
20542     68/push 0/imm32/write
20543     89/<- %ecx 4/r32/esp
20544     # var word-slice/edx: slice
20545     68/push 0/imm32/end
20546     68/push 0/imm32/start
20547     89/<- %edx 4/r32/esp
20548     # var v/esi: (handle var)
20549     68/push 0/imm32
20550     68/push 0/imm32
20551     89/<- %esi 4/r32/esp
20552     # var r/ebx: (handle typeinfo-entry)
20553     68/push 0/imm32
20554     68/push 0/imm32
20555     89/<- %ebx 4/r32/esp
20556     {
20557 $populate-mu-type:line-loop:
20558       (clear-stream %ecx)
20559       (read-line-buffered *(ebp+8) %ecx)
20560       # if (line->write == 0) abort
20561       81 7/subop/compare *ecx 0/imm32
20562       0f 84/jump-if-= $populate-mu-type:error1/disp32
20563 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
20569       (next-mu-token %ecx %edx)
20570       # if slice-empty?(word-slice) continue
20571       (slice-empty? %edx)  # => eax
20572       3d/compare-eax-and 0/imm32
20573       0f 85/jump-if-!= loop/disp32
20574       # if slice-equal?(word-slice, "}") break
20575       (slice-equal? %edx "}")
20576       3d/compare-eax-and 0/imm32
20577       0f 85/jump-if-!= break/disp32
20578 $populate-mu-type:parse-element:
20579       # v = parse-var-with-type(word-slice, first-line)
20580       # must do this first to strip the trailing ':' from word-slice before
20581       # using it in find-or-create-typeinfo-fields below
20582       # TODO: clean up that mutation in parse-var-with-type
20583       (type-name *edi)  # Typeinfo-id => eax
20584       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
20585       # if v is an addr, abort
20586       (lookup *esi *(esi+4))  # => eax
20587       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20588       (mu-addr-type? %eax)  # => eax
20589       3d/compare-eax-and 0/imm32/false
20590       0f 85/jump-if-!= $populate-mu-type:error2/disp32
20591       # if v is an array, abort  (we could support it, but initialization gets complex)
20592       (lookup *esi *(esi+4))  # => eax
20593       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20594       (mu-array-type? %eax)  # => eax
20595       3d/compare-eax-and 0/imm32/false
20596       0f 85/jump-if-!= $populate-mu-type:error3/disp32
20597       # if v is a byte, abort
20598       (lookup *esi *(esi+4))  # => eax
20599       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20600       (simple-mu-type? %eax 8)  # byte => eax
20601       3d/compare-eax-and 0/imm32/false
20602       0f 85/jump-if-!= $populate-mu-type:error4/disp32
20603       # if v is a slice, abort
20604       (lookup *esi *(esi+4))  # => eax
20605       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20606       (simple-mu-type? %eax 0xc)  # slice => eax
20607       3d/compare-eax-and 0/imm32/false
20608       0f 85/jump-if-!= $populate-mu-type:error5/disp32
20609       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
20610       (lookup *esi *(esi+4))  # => eax
20611       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20612       (mu-stream-type? %eax)  # => eax
20613       3d/compare-eax-and 0/imm32/false
20614       0f 85/jump-if-!= $populate-mu-type:error6/disp32
20615       # var tmp/ecx
20616       51/push-ecx
20617 $populate-mu-type:create-typeinfo-fields:
20618       # var r/ebx: (handle typeinfo-entry)
20619       (find-or-create-typeinfo-fields %edi %edx %ebx)
20620       # r->index = curr-index
20621       (lookup *ebx *(ebx+4))  # => eax
20622       8b/-> *(ebp-4) 1/r32/ecx
20623 #?       (write-buffered Stderr "saving index ")
20624 #?       (write-int32-hex-buffered Stderr %ecx)
20625 #?       (write-buffered Stderr " at ")
20626 #?       (write-int32-hex-buffered Stderr %edi)
20627 #?       (write-buffered Stderr Newline)
20628 #?       (flush Stderr)
20629       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
20630       # ++curr-index
20631       ff 0/subop/increment *(ebp-4)
20632 $populate-mu-type:set-input-type:
20633       # r->input-var = v
20634       8b/-> *esi 1/r32/ecx
20635       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
20636       8b/-> *(esi+4) 1/r32/ecx
20637       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
20638       # restore line
20639       59/pop-to-ecx
20640       {
20641 $populate-mu-type:create-output-type:
20642         # if (r->output-var == 0) create a new var with some placeholder data
20643         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
20644         75/jump-if-!= break/disp8
20645         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
20646         (new-literal Heap %edx %eax)
20647       }
20648       e9/jump loop/disp32
20649     }
20650 $populate-mu-type:invalidate-total-size-in-bytes:
20651     # Offsets and total size may not be accurate here since we may not yet
20652     # have encountered the element types.
20653     # We'll recompute them separately after parsing the entire program.
20654     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
20655 $populate-mu-type:end:
20656     # . reclaim locals
20657     81 0/subop/add %esp 0x224/imm32
20658     # . restore registers
20659     5f/pop-to-edi
20660     5e/pop-to-esi
20661     5b/pop-to-ebx
20662     5a/pop-to-edx
20663     59/pop-to-ecx
20664     58/pop-to-eax
20665     # reclaim curr-index
20666     81 0/subop/add %esp 4/imm32
20667     # . epilogue
20668     89/<- %esp 5/r32/ebp
20669     5d/pop-to-ebp
20670     c3/return
20671 
20672 $populate-mu-type:error1:
20673     # error("incomplete type definition '" t->name "'\n")
20674     (write-buffered *(ebp+0x10) "incomplete type definition '")
20675     (type-name *edi)  # Typeinfo-id => eax
20676     (write-buffered *(ebp+0x10) %eax)
20677     (write-buffered *(ebp+0x10) "\n")
20678     (flush *(ebp+0x10))
20679     (stop *(ebp+0x14) 1)
20680     # never gets here
20681 
20682 $populate-mu-type:error2:
20683     (write-buffered *(ebp+0x10) "type ")
20684     (type-name *edi)  # Typeinfo-id => eax
20685     (write-buffered *(ebp+0x10) %eax)
20686     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
20687     (flush *(ebp+0x10))
20688     (stop *(ebp+0x14) 1)
20689     # never gets here
20690 
20691 $populate-mu-type:error3:
20692     (write-buffered *(ebp+0x10) "type ")
20693     (type-name *edi)  # Typeinfo-id => eax
20694     (write-buffered *(ebp+0x10) %eax)
20695     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
20696     (flush *(ebp+0x10))
20697     (stop *(ebp+0x14) 1)
20698     # never gets here
20699 
20700 $populate-mu-type:error4:
20701     (write-buffered *(ebp+0x10) "type ")
20702     (type-name *edi)  # Typeinfo-id => eax
20703     (write-buffered *(ebp+0x10) %eax)
20704     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
20705     (flush *(ebp+0x10))
20706     (stop *(ebp+0x14) 1)
20707     # never gets here
20708 
20709 $populate-mu-type:error5:
20710     (write-buffered *(ebp+0x10) "type ")
20711     (type-name *edi)  # Typeinfo-id => eax
20712     (write-buffered *(ebp+0x10) %eax)
20713     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
20714     (flush *(ebp+0x10))
20715     (stop *(ebp+0x14) 1)
20716     # never gets here
20717 
20718 $populate-mu-type:error6:
20719     (write-buffered *(ebp+0x10) "type ")
20720     (type-name *edi)  # Typeinfo-id => eax
20721     (write-buffered *(ebp+0x10) %eax)
20722     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
20723     (flush *(ebp+0x10))
20724     (stop *(ebp+0x14) 1)
20725     # never gets here
20726 
20727 type-name:  # index: int -> result/eax: (addr array byte)
20728     # . prologue
20729     55/push-ebp
20730     89/<- %ebp 4/r32/esp
20731     #
20732     (index Type-id *(ebp+8))
20733 $type-name:end:
20734     # . epilogue
20735     89/<- %esp 5/r32/ebp
20736     5d/pop-to-ebp
20737     c3/return
20738 
20739 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
20740     # . prologue
20741     55/push-ebp
20742     89/<- %ebp 4/r32/esp
20743     # . save registers
20744     56/push-esi
20745     # TODO: bounds-check index
20746     # esi = arr
20747     8b/-> *(ebp+8) 6/r32/esi
20748     # eax = index
20749     8b/-> *(ebp+0xc) 0/r32/eax
20750     # eax = *(arr + 12 + index)
20751     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
20752 $index:end:
20753     # . restore registers
20754     5e/pop-to-esi
20755     # . epilogue
20756     89/<- %esp 5/r32/ebp
20757     5d/pop-to-ebp
20758     c3/return
20759 
20760 #######################################################
20761 # Compute type sizes
20762 #######################################################
20763 
20764 # Compute the sizes of all user-defined types.
20765 # We'll need the sizes of their elements, which may be other user-defined
20766 # types, which we will compute as needed.
20767 
20768 # Initially, all user-defined types have their sizes set to -2 (invalid)
20769 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
20770     # . prologue
20771     55/push-ebp
20772     89/<- %ebp 4/r32/esp
20773 $populate-mu-type-sizes:total-sizes:
20774     # var curr/eax: (addr typeinfo) = lookup(Program->types)
20775     (lookup *_Program-types *_Program-types->payload)  # => eax
20776     {
20777       # if (curr == null) break
20778       3d/compare-eax-and 0/imm32/null
20779       74/jump-if-= break/disp8
20780       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
20781       # curr = lookup(curr->next)
20782       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20783       eb/jump loop/disp8
20784     }
20785 $populate-mu-type-sizes:offsets:
20786     # curr = *Program->types
20787     (lookup *_Program-types *_Program-types->payload)  # => eax
20788     {
20789       # if (curr == null) break
20790       3d/compare-eax-and 0/imm32/null
20791       74/jump-if-= break/disp8
20792       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
20793       # curr = curr->next
20794       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
20795       eb/jump loop/disp8
20796     }
20797 $populate-mu-type-sizes:end:
20798     # . epilogue
20799     89/<- %esp 5/r32/ebp
20800     5d/pop-to-ebp
20801     c3/return
20802 
20803 # compute sizes of all fields, recursing as necessary
20804 # sum up all their sizes to arrive at total size
20805 # fields may be out of order, but that doesn't affect the answer
20806 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20807     # . prologue
20808     55/push-ebp
20809     89/<- %ebp 4/r32/esp
20810     # . save registers
20811     50/push-eax
20812     51/push-ecx
20813     52/push-edx
20814     56/push-esi
20815     57/push-edi
20816     # esi = T
20817     8b/-> *(ebp+8) 6/r32/esi
20818     # if T is already computed, return
20819     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
20820     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
20821     # if T is being computed, abort
20822     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20823     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
20824     # tag T (-2 to -1) to avoid infinite recursion
20825     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
20826     # var total-size/edi: int = 0
20827     bf/copy-to-edi 0/imm32
20828     # - for every field, if it's a user-defined type, compute its size
20829     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
20830     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
20831     89/<- %ecx 0/r32/eax
20832     # var table-size/edx: int = table->write
20833     8b/-> *ecx 2/r32/edx  # stream-write
20834     # var curr/ecx: (addr table_row) = table->data
20835     8d/copy-address *(ecx+0xc) 1/r32/ecx
20836     # var max/edx: (addr table_row) = table->data + table->write
20837     8d/copy-address *(ecx+edx) 2/r32/edx
20838     {
20839 $populate-mu-type-sizes-in-type:loop:
20840       # if (curr >= max) break
20841       39/compare %ecx 2/r32/edx
20842       73/jump-if-addr>= break/disp8
20843       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
20844       (lookup *(ecx+8) *(ecx+0xc))  # => eax
20845       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
20846       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
20847       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
20848       # compute size of t->input-var
20849       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
20850       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
20851       # result += eax
20852       01/add-to %edi 0/r32/eax
20853       # curr += row-size
20854       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
20855       #
20856       eb/jump loop/disp8
20857     }
20858     # - save result
20859     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
20860 $populate-mu-type-sizes-in-type:end:
20861     # . restore registers
20862     5f/pop-to-edi
20863     5e/pop-to-esi
20864     5a/pop-to-edx
20865     59/pop-to-ecx
20866     58/pop-to-eax
20867     # . epilogue
20868     89/<- %esp 5/r32/ebp
20869     5d/pop-to-ebp
20870     c3/return
20871 
20872 $populate-mu-type-sizes-in-type:abort:
20873     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
20874     (flush *(ebp+0xc))
20875     (stop *(ebp+0x10) 1)
20876     # never gets here
20877 
20878 # Analogous to size-of, except we need to compute what size-of can just read
20879 # off the right data structures.
20880 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20881     # . prologue
20882     55/push-ebp
20883     89/<- %ebp 4/r32/esp
20884     # . push registers
20885     51/push-ecx
20886     # var t/ecx: (addr type-tree) = lookup(v->type)
20887     8b/-> *(ebp+8) 1/r32/ecx
20888     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
20889     89/<- %ecx 0/r32/eax
20890     # if (t->is-atom == false) t = lookup(t->left)
20891     {
20892       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
20893       75/jump-if-!= break/disp8
20894       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
20895       89/<- %ecx 0/r32/eax
20896     }
20897     # TODO: ensure t is an atom
20898     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
20899 $compute-size-of-var:end:
20900     # . restore registers
20901     59/pop-to-ecx
20902     # . epilogue
20903     89/<- %esp 5/r32/ebp
20904     5d/pop-to-ebp
20905     c3/return
20906 
20907 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
20908     # . prologue
20909     55/push-ebp
20910     89/<- %ebp 4/r32/esp
20911     # . save registers
20912     51/push-ecx
20913     # var out/ecx: (handle typeinfo)
20914     68/push 0/imm32
20915     68/push 0/imm32
20916     89/<- %ecx 4/r32/esp
20917     # eax = t
20918     8b/-> *(ebp+8) 0/r32/eax
20919     # if t is a literal, return 0
20920     3d/compare-eax-and 0/imm32/literal
20921     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
20922     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
20923     3d/compare-eax-and 8/imm32/byte
20924     {
20925       75/jump-if-!= break/disp8
20926       b8/copy-to-eax 4/imm32
20927       eb/jump $compute-size-of-type-id:end/disp8
20928     }
20929     # if t is a handle, return 8
20930     3d/compare-eax-and 4/imm32/handle
20931     {
20932       75/jump-if-!= break/disp8
20933       b8/copy-to-eax 8/imm32
20934       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20935     }
20936     # if t is a slice, return 8
20937     3d/compare-eax-and 0xc/imm32/slice
20938     {
20939       75/jump-if-!= break/disp8
20940       b8/copy-to-eax 8/imm32
20941       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
20942     }
20943     # if t is a user-defined type, compute its size
20944     # TODO: support non-atom type
20945     (find-typeinfo %eax %ecx)
20946     {
20947       81 7/subop/compare *ecx 0/imm32
20948       74/jump-if-= break/disp8
20949 $compute-size-of-type-id:user-defined:
20950       (lookup *ecx *(ecx+4))  # => eax
20951       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
20952       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
20953       eb/jump $compute-size-of-type-id:end/disp8
20954     }
20955     # otherwise return the word size
20956     b8/copy-to-eax 4/imm32
20957 $compute-size-of-type-id:end:
20958     # . reclaim locals
20959     81 0/subop/add %esp 8/imm32
20960     # . restore registers
20961     59/pop-to-ecx
20962     # . epilogue
20963     89/<- %esp 5/r32/ebp
20964     5d/pop-to-ebp
20965     c3/return
20966 
20967 # at this point we have total sizes for all user-defined types
20968 # compute offsets for each element
20969 # complication: fields may be out of order
20970 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
20971     # . prologue
20972     55/push-ebp
20973     89/<- %ebp 4/r32/esp
20974     # . save registers
20975     50/push-eax
20976     51/push-ecx
20977     52/push-edx
20978     53/push-ebx
20979     56/push-esi
20980     57/push-edi
20981 #?     (dump-typeinfos "aaa\n")
20982     # var curr-offset/edi: int = 0
20983     bf/copy-to-edi 0/imm32
20984     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
20985     8b/-> *(ebp+8) 1/r32/ecx
20986     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
20987     89/<- %ecx 0/r32/eax
20988     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
20989     8b/-> *ecx 2/r32/edx  # stream-write
20990     c1 5/subop/shift-right-logical  %edx 4/imm8
20991     # var i/ebx: int = 0
20992     bb/copy-to-ebx 0/imm32
20993     {
20994 $populate-mu-type-offsets:loop:
20995       39/compare %ebx 2/r32/edx
20996       0f 8d/jump-if->= break/disp32
20997 #?       (write-buffered Stderr "looking up index ")
20998 #?       (write-int32-hex-buffered Stderr %ebx)
20999 #?       (write-buffered Stderr " in ")
21000 #?       (write-int32-hex-buffered Stderr *(ebp+8))
21001 #?       (write-buffered Stderr Newline)
21002 #?       (flush Stderr)
21003       # var v/esi: (addr typeinfo-entry)
21004       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
21005       89/<- %esi 0/r32/eax
21006       # if v is null, silently move on; we'll emit a nice error message while type-checking
21007       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
21008       74/jump-if-= $populate-mu-type-offsets:end/disp8
21009       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
21010       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
21011       74/jump-if-= $populate-mu-type-offsets:end/disp8
21012       # v->output-var->offset = curr-offset
21013       # . eax: (addr var)
21014       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
21015       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
21016       # curr-offset += size-of(v->input-var)
21017       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
21018       (size-of %eax)  # => eax
21019       01/add-to %edi 0/r32/eax
21020       # ++i
21021       43/increment-ebx
21022       e9/jump loop/disp32
21023     }
21024 $populate-mu-type-offsets:end:
21025     # . restore registers
21026     5f/pop-to-edi
21027     5e/pop-to-esi
21028     5b/pop-to-ebx
21029     5a/pop-to-edx
21030     59/pop-to-ecx
21031     58/pop-to-eax
21032     # . epilogue
21033     89/<- %esp 5/r32/ebp
21034     5d/pop-to-ebp
21035     c3/return
21036 
21037 locate-typeinfo-entry-with-index:  # table: (addr table (handle array byte) (handle typeinfo-entry)), idx: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: (addr typeinfo-entry)
21038     # . prologue
21039     55/push-ebp
21040     89/<- %ebp 4/r32/esp
21041     # . save registers
21042     51/push-ecx
21043     52/push-edx
21044     53/push-ebx
21045     56/push-esi
21046     57/push-edi
21047     # esi = table
21048     8b/-> *(ebp+8) 6/r32/esi
21049     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
21050     8d/copy-address *(esi+0xc) 1/r32/ecx
21051     # var max/edx: (addr byte) = &table->data[table->write]
21052     8b/-> *esi 2/r32/edx
21053     8d/copy-address *(ecx+edx) 2/r32/edx
21054     {
21055 $locate-typeinfo-entry-with-index:loop:
21056       39/compare %ecx 2/r32/edx
21057       73/jump-if-addr>= break/disp8
21058       # var v/eax: (addr typeinfo-entry)
21059       (lookup *(ecx+8) *(ecx+0xc))  # => eax
21060       # if (v->index == idx) return v
21061       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
21062 #?       (write-buffered Stderr "comparing ")
21063 #?       (write-int32-hex-buffered Stderr %ebx)
21064 #?       (write-buffered Stderr " and ")
21065 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
21066 #?       (write-buffered Stderr Newline)
21067 #?       (flush Stderr)
21068       39/compare *(ebp+0xc) 3/r32/ebx
21069       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
21070       # curr += Typeinfo-entry-size
21071       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
21072       #
21073       eb/jump loop/disp8
21074     }
21075     # return 0
21076     b8/copy-to-eax 0/imm32
21077 $locate-typeinfo-entry-with-index:end:
21078 #?     (write-buffered Stderr "returning ")
21079 #?     (write-int32-hex-buffered Stderr %eax)
21080 #?     (write-buffered Stderr Newline)
21081 #?     (flush Stderr)
21082     # . restore registers
21083     5f/pop-to-edi
21084     5e/pop-to-esi
21085     5b/pop-to-ebx
21086     5a/pop-to-edx
21087     59/pop-to-ecx
21088     # . epilogue
21089     89/<- %esp 5/r32/ebp
21090     5d/pop-to-ebp
21091     c3/return
21092 
21093 dump-typeinfos:  # hdr: (addr array byte)
21094     # . prologue
21095     55/push-ebp
21096     89/<- %ebp 4/r32/esp
21097     # . save registers
21098     50/push-eax
21099     #
21100     (write-buffered Stderr *(ebp+8))
21101     (flush Stderr)
21102     # var curr/eax: (addr typeinfo) = lookup(Program->types)
21103     (lookup *_Program-types *_Program-types->payload)  # => eax
21104     {
21105       # if (curr == null) break
21106       3d/compare-eax-and 0/imm32
21107       74/jump-if-= break/disp8
21108       (write-buffered Stderr "---\n")
21109       (flush Stderr)
21110       (dump-typeinfo %eax)
21111       # curr = lookup(curr->next)
21112       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
21113       eb/jump loop/disp8
21114     }
21115 $dump-typeinfos:end:
21116     # . restore registers
21117     58/pop-to-eax
21118     # . epilogue
21119     89/<- %esp 5/r32/ebp
21120     5d/pop-to-ebp
21121     c3/return
21122 
21123 dump-typeinfo:  # in: (addr typeinfo)
21124     # . prologue
21125     55/push-ebp
21126     89/<- %ebp 4/r32/esp
21127     # . save registers
21128     50/push-eax
21129     51/push-ecx
21130     52/push-edx
21131     53/push-ebx
21132     56/push-esi
21133     57/push-edi
21134     # esi = in
21135     8b/-> *(ebp+8) 6/r32/esi
21136     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
21137     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
21138     89/<- %ecx 0/r32/eax
21139     (write-buffered Stderr "id:")
21140     (write-int32-hex-buffered Stderr *esi)
21141     (write-buffered Stderr "\n")
21142     (write-buffered Stderr "fields @ ")
21143     (write-int32-hex-buffered Stderr %ecx)
21144     (write-buffered Stderr Newline)
21145     (flush Stderr)
21146     (write-buffered Stderr "  write: ")
21147     (write-int32-hex-buffered Stderr *ecx)
21148     (write-buffered Stderr Newline)
21149     (flush Stderr)
21150     (write-buffered Stderr "  read: ")
21151     (write-int32-hex-buffered Stderr *(ecx+4))
21152     (write-buffered Stderr Newline)
21153     (flush Stderr)
21154     (write-buffered Stderr "  size: ")
21155     (write-int32-hex-buffered Stderr *(ecx+8))
21156     (write-buffered Stderr Newline)
21157     (flush Stderr)
21158     # var table-size/edx: int = table->write
21159     8b/-> *ecx 2/r32/edx  # stream-write
21160     # var curr/ecx: (addr table_row) = table->data
21161     8d/copy-address *(ecx+0xc) 1/r32/ecx
21162     # var max/edx: (addr table_row) = table->data + table->write
21163     8d/copy-address *(ecx+edx) 2/r32/edx
21164     {
21165 $dump-typeinfo:loop:
21166       # if (curr >= max) break
21167       39/compare %ecx 2/r32/edx
21168       0f 83/jump-if-addr>= break/disp32
21169       (write-buffered Stderr "  row:\n")
21170       (write-buffered Stderr "    key: ")
21171       (write-int32-hex-buffered Stderr *ecx)
21172       (write-buffered Stderr ",")
21173       (write-int32-hex-buffered Stderr *(ecx+4))
21174       (write-buffered Stderr " = '")
21175       (lookup *ecx *(ecx+4))
21176       (write-buffered Stderr %eax)
21177       (write-buffered Stderr "' @ ")
21178       (write-int32-hex-buffered Stderr %eax)
21179       (write-buffered Stderr Newline)
21180       (flush Stderr)
21181       (write-buffered Stderr "    value: ")
21182       (write-int32-hex-buffered Stderr *(ecx+8))
21183       (write-buffered Stderr ",")
21184       (write-int32-hex-buffered Stderr *(ecx+0xc))
21185       (write-buffered Stderr " = typeinfo-entry@")
21186       (lookup *(ecx+8) *(ecx+0xc))
21187       (write-int32-hex-buffered Stderr %eax)
21188       (write-buffered Stderr Newline)
21189       (flush Stderr)
21190       (write-buffered Stderr "        input var@")
21191       (dump-var 5 %eax)
21192       (lookup *(ecx+8) *(ecx+0xc))
21193       (write-buffered Stderr "        index: ")
21194       (write-int32-hex-buffered Stderr *(eax+8))
21195       (write-buffered Stderr Newline)
21196       (flush Stderr)
21197       (write-buffered Stderr "        output var@")
21198       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
21199       (dump-var 5 %eax)
21200       (flush Stderr)
21201       # curr += row-size
21202       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
21203       #
21204       e9/jump loop/disp32
21205     }
21206 $dump-typeinfo:end:
21207     # . restore registers
21208     5f/pop-to-edi
21209     5e/pop-to-esi
21210     5b/pop-to-ebx
21211     5a/pop-to-edx
21212     59/pop-to-ecx
21213     58/pop-to-eax
21214     # . epilogue
21215     89/<- %esp 5/r32/ebp
21216     5d/pop-to-ebp
21217     c3/return
21218 
21219 dump-var:  # indent: int, v: (addr handle var)
21220     # . prologue
21221     55/push-ebp
21222     89/<- %ebp 4/r32/esp
21223     # . save registers
21224     50/push-eax
21225     53/push-ebx
21226     # eax = v
21227     8b/-> *(ebp+0xc) 0/r32/eax
21228     #
21229     (write-int32-hex-buffered Stderr *eax)
21230     (write-buffered Stderr ",")
21231     (write-int32-hex-buffered Stderr *(eax+4))
21232     (write-buffered Stderr "->")
21233     (lookup *eax *(eax+4))
21234     (write-int32-hex-buffered Stderr %eax)
21235     (write-buffered Stderr Newline)
21236     (flush Stderr)
21237     {
21238       3d/compare-eax-and 0/imm32
21239       0f 84/jump-if-= break/disp32
21240       (emit-indent Stderr *(ebp+8))
21241       (write-buffered Stderr "name: ")
21242       89/<- %ebx 0/r32/eax
21243       (write-int32-hex-buffered Stderr *ebx)  # Var-name
21244       (write-buffered Stderr ",")
21245       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
21246       (write-buffered Stderr "->")
21247       (lookup *ebx *(ebx+4))  # Var-name
21248       (write-int32-hex-buffered Stderr %eax)
21249       {
21250         3d/compare-eax-and 0/imm32
21251         74/jump-if-= break/disp8
21252         (write-buffered Stderr Space)
21253         (write-buffered Stderr %eax)
21254       }
21255       (write-buffered Stderr Newline)
21256       (flush Stderr)
21257       (emit-indent Stderr *(ebp+8))
21258       (write-buffered Stderr "block depth: ")
21259       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
21260       (write-buffered Stderr Newline)
21261       (flush Stderr)
21262       (emit-indent Stderr *(ebp+8))
21263       (write-buffered Stderr "stack offset: ")
21264       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
21265       (write-buffered Stderr Newline)
21266       (flush Stderr)
21267       (emit-indent Stderr *(ebp+8))
21268       (write-buffered Stderr "reg: ")
21269       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
21270       (write-buffered Stderr ",")
21271       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
21272       (write-buffered Stderr "->")
21273       (flush Stderr)
21274       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
21275       (write-int32-hex-buffered Stderr %eax)
21276       {
21277         3d/compare-eax-and 0/imm32
21278         74/jump-if-= break/disp8
21279         (write-buffered Stderr Space)
21280         (write-buffered Stderr %eax)
21281       }
21282       (write-buffered Stderr Newline)
21283       (flush Stderr)
21284     }
21285 $dump-var:end:
21286     # . restore registers
21287     5b/pop-to-ebx
21288     58/pop-to-eax
21289     # . epilogue
21290     89/<- %esp 5/r32/ebp
21291     5d/pop-to-ebp
21292     c3/return
21293 
21294 #######################################################
21295 # Type-checking
21296 #######################################################
21297 
21298 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
21299     # . prologue
21300     55/push-ebp
21301     89/<- %ebp 4/r32/esp
21302     # . save registers
21303     50/push-eax
21304     # var curr/eax: (addr function) = lookup(Program->functions)
21305     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21306     {
21307 $check-mu-types:loop:
21308       # if (curr == null) break
21309       3d/compare-eax-and 0/imm32
21310       0f 84/jump-if-= break/disp32
21311 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
21319       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
21320       # curr = lookup(curr->next)
21321       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
21322       e9/jump loop/disp32
21323     }
21324 $check-mu-types:end:
21325     # . restore registers
21326     58/pop-to-eax
21327     # . epilogue
21328     89/<- %esp 5/r32/ebp
21329     5d/pop-to-ebp
21330     c3/return
21331 
21332 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21333     # . prologue
21334     55/push-ebp
21335     89/<- %ebp 4/r32/esp
21336     # . save registers
21337     50/push-eax
21338     56/push-esi
21339     # esi = f
21340     8b/-> *(ebp+8) 6/r32/esi
21341     # outputs
21342     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
21343     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
21344     # body
21345     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
21346     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
21347     # if function has no outputs, we're done
21348     81 7/subop/compare *(esi+0x10) 0/imm32
21349     74/jump-if-= $check-mu-function:end/disp8
21350     # some final checks on body
21351     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
21352     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
21353 $check-mu-function:end:
21354     # . restore registers
21355     5e/pop-to-esi
21356     58/pop-to-eax
21357     # . epilogue
21358     89/<- %esp 5/r32/ebp
21359     5d/pop-to-ebp
21360     c3/return
21361 
21362 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21363     # . prologue
21364     55/push-ebp
21365     89/<- %ebp 4/r32/esp
21366     # . save registers
21367     50/push-eax
21368     # eax = block
21369     8b/-> *(ebp+8) 0/r32/eax
21370     # var stmts/eax: (addr list stmt) = lookup(block->statements)
21371     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21372     #
21373     {
21374 $check-mu-block:check-empty:
21375       3d/compare-eax-and 0/imm32
21376       0f 84/jump-if-= break/disp32
21377       # emit block->statements
21378       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21379     }
21380 $check-mu-block:end:
21381     # . restore registers
21382     58/pop-to-eax
21383     # . epilogue
21384     89/<- %esp 5/r32/ebp
21385     5d/pop-to-ebp
21386     c3/return
21387 
21388 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21389     # . prologue
21390     55/push-ebp
21391     89/<- %ebp 4/r32/esp
21392     # . save registers
21393     50/push-eax
21394     56/push-esi
21395     # esi = stmts
21396     8b/-> *(ebp+8) 6/r32/esi
21397     {
21398 $check-mu-stmt-list:loop:
21399       81 7/subop/compare %esi 0/imm32
21400       0f 84/jump-if-= break/disp32
21401       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
21402       (lookup *esi *(esi+4))  # List-value List-value => eax
21403       {
21404 $check-mu-stmt-list:check-for-block:
21405         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
21406         75/jump-if-!= break/disp8
21407 $check-mu-stmt-list:block:
21408         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21409         eb/jump $check-mu-stmt-list:continue/disp8
21410       }
21411       {
21412 $check-mu-stmt-list:check-for-stmt1:
21413         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21414         0f 85/jump-if-!= break/disp32
21415 $check-mu-stmt-list:stmt1:
21416         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21417         eb/jump $check-mu-stmt-list:continue/disp8
21418       }
21419       {
21420 $check-mu-stmt-list:check-for-reg-var-def:
21421         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
21422         0f 85/jump-if-!= break/disp32
21423 $check-mu-stmt-list:reg-var-def:
21424         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21425         eb/jump $check-mu-stmt-list:continue/disp8
21426       }
21427 $check-mu-stmt-list:continue:
21428       # TODO: raise an error on unrecognized Stmt-tag
21429       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
21430       89/<- %esi 0/r32/eax
21431       e9/jump loop/disp32
21432     }
21433 $check-mu-stmt-list:end:
21434     # . restore registers
21435     5e/pop-to-esi
21436     58/pop-to-eax
21437     # . epilogue
21438     89/<- %esp 5/r32/ebp
21439     5d/pop-to-ebp
21440     c3/return
21441 
21442 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21443     # . prologue
21444     55/push-ebp
21445     89/<- %ebp 4/r32/esp
21446     # . save registers
21447     50/push-eax
21448     # - if stmt's operation matches a primitive, check against it
21449     (has-primitive-name? *(ebp+8))  # => eax
21450     3d/compare-eax-and 0/imm32/false
21451     {
21452       74/jump-if-= break/disp8
21453       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21454       e9/jump $check-mu-stmt:end/disp32
21455     }
21456     # - otherwise find a function to check against
21457     # var f/eax: (addr function) = lookup(*Program->functions)
21458     (lookup *_Program-functions *_Program-functions->payload)  # => eax
21459     (find-matching-function %eax *(ebp+8))  # => eax
21460     3d/compare-eax-and 0/imm32
21461     {
21462       74/jump-if-= break/disp8
21463       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21464       eb/jump $check-mu-stmt:end/disp8
21465     }
21466     # var f/eax: (addr function) = lookup(*Program->signatures)
21467     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
21468     (find-matching-function %eax *(ebp+8))  # => eax
21469     3d/compare-eax-and 0/imm32
21470     {
21471       74/jump-if-= break/disp8
21472       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21473       eb/jump $check-mu-stmt:end/disp8
21474     }
21475     # - otherwise abort
21476     e9/jump $check-mu-stmt:unknown-call/disp32
21477 $check-mu-stmt:end:
21478     # . restore registers
21479     58/pop-to-eax
21480     # . epilogue
21481     89/<- %esp 5/r32/ebp
21482     5d/pop-to-ebp
21483     c3/return
21484 
21485 $check-mu-stmt:unknown-call:
21486     (write-buffered *(ebp+0x10) "unknown function '")
21487     8b/-> *(ebp+8) 0/r32/eax
21488     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21489     (write-buffered *(ebp+0x10) %eax)
21490     (write-buffered *(ebp+0x10) "'\n")
21491     (flush *(ebp+0x10))
21492     (stop *(ebp+0x14) 1)
21493     # never gets here
21494 
21495 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
21496     # . prologue
21497     55/push-ebp
21498     89/<- %ebp 4/r32/esp
21499     # . save registers
21500     51/push-ecx
21501     56/push-esi
21502     # var name/esi: (addr array byte) = lookup(stmt->operation)
21503     8b/-> *(ebp+8) 6/r32/esi
21504     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21505     89/<- %esi 0/r32/eax
21506     # if (name == "return") return true
21507     (string-equal? %esi "return")  # => eax
21508     3d/compare-eax-and 0/imm32/false
21509     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21510     # if (name == "get") return true
21511     (string-equal? %esi "get")  # => eax
21512     3d/compare-eax-and 0/imm32/false
21513     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21514     # if (name == "index") return true
21515     (string-equal? %esi "index")  # => eax
21516     3d/compare-eax-and 0/imm32/false
21517     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21518     # if (name == "length") return true
21519     (string-equal? %esi "length")  # => eax
21520     3d/compare-eax-and 0/imm32/false
21521     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21522     # if (name == "compute-offset") return true
21523     (string-equal? %esi "compute-offset")  # => eax
21524     3d/compare-eax-and 0/imm32/false
21525     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21526     # if (name == "copy-object") return true
21527     (string-equal? %esi "copy-object")  # => eax
21528     3d/compare-eax-and 0/imm32/false
21529     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21530     # if (name == "clear-object") return true
21531     (string-equal? %esi "clear-object")  # => eax
21532     3d/compare-eax-and 0/imm32/false
21533     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21534     # if (name == "allocate") return true
21535     (string-equal? %esi "allocate")  # => eax
21536     3d/compare-eax-and 0/imm32/false
21537     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21538     # if (name == "populate") return true
21539     (string-equal? %esi "populate")  # => eax
21540     3d/compare-eax-and 0/imm32/false
21541     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21542     # if (name == "populate-stream") return true
21543     (string-equal? %esi "populate-stream")  # => eax
21544     3d/compare-eax-and 0/imm32/false
21545     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21546     # if (name == "read-from-stream") return true
21547     (string-equal? %esi "read-from-stream")  # => eax
21548     3d/compare-eax-and 0/imm32/false
21549     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21550     # if (name == "write-to-stream") return true
21551     (string-equal? %esi "write-to-stream")  # => eax
21552     3d/compare-eax-and 0/imm32/false
21553     0f 85/jump-if-!= $has-primitive-name?:end/disp32
21554     # var curr/ecx: (addr primitive) = Primitives
21555     b9/copy-to-ecx Primitives/imm32
21556     {
21557 $has-primitive-name?:loop:
21558       # if (curr == null) break
21559       81 7/subop/compare %ecx 0/imm32
21560       74/jump-if-= break/disp8
21561       # if (primitive->name == name) return true
21562       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
21563 #?       (write-buffered Stderr %eax)
21564 #?       (write-buffered Stderr Newline)
21565 #?       (flush Stderr)
21566       (string-equal? %esi %eax)  # => eax
21567       3d/compare-eax-and 0/imm32/false
21568       75/jump-if-!= $has-primitive-name?:end/disp8
21569 $has-primitive-name?:next-primitive:
21570       # curr = curr->next
21571       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
21572       89/<- %ecx 0/r32/eax
21573       #
21574       e9/jump loop/disp32
21575     }
21576     # return null
21577     b8/copy-to-eax 0/imm32
21578 $has-primitive-name?:end:
21579     # . restore registers
21580     5e/pop-to-esi
21581     59/pop-to-ecx
21582     # . epilogue
21583     89/<- %esp 5/r32/ebp
21584     5d/pop-to-ebp
21585     c3/return
21586 
21587 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21588     # . prologue
21589     55/push-ebp
21590     89/<- %ebp 4/r32/esp
21591     # . save registers
21592     50/push-eax
21593     51/push-ecx
21594     # var op/ecx: (addr array byte) = lookup(stmt->operation)
21595     8b/-> *(ebp+8) 0/r32/eax
21596     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21597     89/<- %ecx 0/r32/eax
21598     # if (op == "copy") check-mu-copy-stmt
21599     {
21600       (string-equal? %ecx "copy")  # => eax
21601       3d/compare-eax-and 0/imm32/false
21602       74/jump-if-= break/disp8
21603       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21604       e9/jump $check-mu-primitive:end/disp32
21605     }
21606     # if (op == "copy-to") check-mu-copy-to-stmt
21607     {
21608       (string-equal? %ecx "copy-to")  # => eax
21609       3d/compare-eax-and 0/imm32/false
21610       74/jump-if-= break/disp8
21611       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21612       e9/jump $check-mu-primitive:end/disp32
21613     }
21614     # if (op == "copy-byte") check-mu-copy-byte-stmt
21615     {
21616       (string-equal? %ecx "copy-byte")  # => eax
21617       3d/compare-eax-and 0/imm32/false
21618       74/jump-if-= break/disp8
21619       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21620       e9/jump $check-mu-primitive:end/disp32
21621     }
21622     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
21623     {
21624       (string-equal? %ecx "copy-byte-to")  # => eax
21625       3d/compare-eax-and 0/imm32/false
21626       74/jump-if-= break/disp8
21627       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21628       e9/jump $check-mu-primitive:end/disp32
21629     }
21630     # if (op == "compare") check-mu-compare-stmt
21631     {
21632       (string-equal? %ecx "compare")  # => eax
21633       3d/compare-eax-and 0/imm32/false
21634       74/jump-if-= break/disp8
21635       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21636       e9/jump $check-mu-primitive:end/disp32
21637     }
21638     # if (op == "address") check-mu-address-stmt
21639     {
21640       (string-equal? %ecx "address")  # => eax
21641       3d/compare-eax-and 0/imm32/false
21642       74/jump-if-= break/disp8
21643       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21644       e9/jump $check-mu-primitive:end/disp32
21645     }
21646     # if (op == "return") check-mu-return-stmt
21647     {
21648       (string-equal? %ecx "return")  # => eax
21649       3d/compare-eax-and 0/imm32/false
21650       74/jump-if-= break/disp8
21651       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21652       e9/jump $check-mu-primitive:end/disp32
21653     }
21654     # if (op == "get") check-mu-get-stmt
21655     {
21656       (string-equal? %ecx "get")  # => eax
21657       3d/compare-eax-and 0/imm32/false
21658       74/jump-if-= break/disp8
21659       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21660       e9/jump $check-mu-primitive:end/disp32
21661     }
21662     # if (op == "index") check-mu-index-stmt
21663     {
21664       (string-equal? %ecx "index")  # => eax
21665       3d/compare-eax-and 0/imm32/false
21666       74/jump-if-= break/disp8
21667       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21668       e9/jump $check-mu-primitive:end/disp32
21669     }
21670     # if (op == "length") check-mu-length-stmt
21671     {
21672       (string-equal? %ecx "length")  # => eax
21673       3d/compare-eax-and 0/imm32/false
21674       74/jump-if-= break/disp8
21675       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21676       e9/jump $check-mu-primitive:end/disp32
21677     }
21678     # if (op == "compute-offset") check-mu-compute-offset-stmt
21679     {
21680       (string-equal? %ecx "compute-offset")  # => eax
21681       3d/compare-eax-and 0/imm32/false
21682       74/jump-if-= break/disp8
21683       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21684       e9/jump $check-mu-primitive:end/disp32
21685     }
21686     # if (op == "copy-object") check-mu-copy-object-stmt
21687     {
21688       (string-equal? %ecx "copy-object")  # => eax
21689       3d/compare-eax-and 0/imm32/false
21690       74/jump-if-= break/disp8
21691       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21692       e9/jump $check-mu-primitive:end/disp32
21693     }
21694     # if (op == "clear-object") check-mu-clear-object-stmt
21695     {
21696       (string-equal? %ecx "clear-object")  # => eax
21697       3d/compare-eax-and 0/imm32/false
21698       74/jump-if-= break/disp8
21699       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21700       e9/jump $check-mu-primitive:end/disp32
21701     }
21702     # if (op == "allocate") check-mu-allocate-stmt
21703     {
21704       (string-equal? %ecx "allocate")  # => eax
21705       3d/compare-eax-and 0/imm32/false
21706       74/jump-if-= break/disp8
21707       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21708       e9/jump $check-mu-primitive:end/disp32
21709     }
21710     # if (op == "populate") check-mu-populate-stmt
21711     {
21712       (string-equal? %ecx "populate")  # => eax
21713       3d/compare-eax-and 0/imm32/false
21714       74/jump-if-= break/disp8
21715       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21716       e9/jump $check-mu-primitive:end/disp32
21717     }
21718     # if (op == "populate-stream") check-mu-populate-stream-stmt
21719     {
21720       (string-equal? %ecx "populate-stream")  # => eax
21721       3d/compare-eax-and 0/imm32/false
21722       74/jump-if-= break/disp8
21723       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21724       e9/jump $check-mu-primitive:end/disp32
21725     }
21726     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
21727     {
21728       (string-equal? %ecx "read-from-stream")  # => eax
21729       3d/compare-eax-and 0/imm32/false
21730       74/jump-if-= break/disp8
21731       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21732       e9/jump $check-mu-primitive:end/disp32
21733     }
21734     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
21735     {
21736       (string-equal? %ecx "write-to-stream")  # => eax
21737       3d/compare-eax-and 0/imm32/false
21738       74/jump-if-= break/disp8
21739       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21740       e9/jump $check-mu-primitive:end/disp32
21741     }
21742     # if (op == "convert") check-mu-convert-stmt
21743     {
21744       (string-equal? %ecx "convert")  # => eax
21745       3d/compare-eax-and 0/imm32/false
21746       74/jump-if-= break/disp8
21747       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21748       e9/jump $check-mu-primitive:end/disp32
21749     }
21750     # otherwise check-numberlike-stmt
21751     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21752 $check-mu-primitive:end:
21753     # . restore registers
21754     59/pop-to-ecx
21755     58/pop-to-eax
21756     # . epilogue
21757     89/<- %esp 5/r32/ebp
21758     5d/pop-to-ebp
21759     c3/return
21760 
21761 # by default, Mu primitives should only operate on 'number-like' types
21762 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21763     # . prologue
21764     55/push-ebp
21765     89/<- %ebp 4/r32/esp
21766     # . save registers
21767     50/push-eax
21768     51/push-ecx
21769     56/push-esi
21770     # esi = stmt
21771     8b/-> *(ebp+8) 6/r32/esi
21772     # var gas/ecx: int = 2
21773     b9/copy-to-ecx 2/imm32
21774     # - check at most 1 output
21775     # var output/eax: (addr stmt-var) = stmt->outputs
21776     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21777     {
21778       3d/compare-eax-and 0/imm32
21779       74/jump-if-= break/disp8
21780 $check-mu-numberlike-primitive:output:
21781       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21782       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21783       3d/compare-eax-and 0/imm32
21784       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
21785       # check output is in a register
21786       # --gas
21787       49/decrement-ecx
21788     }
21789     # - check first inout
21790     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21791     {
21792       3d/compare-eax-and 0/imm32
21793       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
21794 $check-mu-numberlike-primitive:first-inout:
21795       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21796       # --gas
21797       49/decrement-ecx
21798     }
21799     # - check second inout
21800     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21801     {
21802       3d/compare-eax-and 0/imm32
21803       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
21804 $check-mu-numberlike-primitive:second-inout:
21805       # is a second inout allowed?
21806       81 7/subop/compare %ecx 0/imm32
21807       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21808 $check-mu-numberlike-primitive:second-inout-permitted:
21809       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
21810     }
21811 $check-mu-numberlike-primitive:third-inout:
21812     # if there's a third arg, raise an error
21813     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
21814     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
21815 $check-mu-numberlike-primitive:end:
21816     # . restore registers
21817     5e/pop-to-esi
21818     59/pop-to-ecx
21819     58/pop-to-eax
21820     # . epilogue
21821     89/<- %esp 5/r32/ebp
21822     5d/pop-to-ebp
21823     c3/return
21824 
21825 $check-mu-numberlike-primitive:error-too-many-inouts:
21826     (write-buffered *(ebp+0x10) "fn ")
21827     8b/-> *(ebp+0xc) 0/r32/eax
21828     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21829     (write-buffered *(ebp+0x10) %eax)
21830     (write-buffered *(ebp+0x10) ": stmt ")
21831     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21832     (write-buffered *(ebp+0x10) %eax)
21833     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
21834     (flush *(ebp+0x10))
21835     (stop *(ebp+0x14) 1)
21836     # never gets here
21837 
21838 $check-mu-numberlike-primitive:error-too-many-outputs:
21839     (write-buffered *(ebp+0x10) "fn ")
21840     8b/-> *(ebp+0xc) 0/r32/eax
21841     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21842     (write-buffered *(ebp+0x10) %eax)
21843     (write-buffered *(ebp+0x10) ": stmt ")
21844     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
21845     (write-buffered *(ebp+0x10) %eax)
21846     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
21847     (flush *(ebp+0x10))
21848     (stop *(ebp+0x14) 1)
21849     # never gets here
21850 
21851 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21852     # . prologue
21853     55/push-ebp
21854     89/<- %ebp 4/r32/esp
21855     # . save registers
21856     50/push-eax
21857     56/push-esi
21858     # var t/esi: (addr type-tree) = lookup(v->value->type)
21859     8b/-> *(ebp+8) 0/r32/eax
21860     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21861     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21862     89/<- %esi 0/r32/eax
21863 $check-mu-numberlike-arg:check-literal:
21864     # if t is an int, return
21865     (simple-mu-type? %esi 0)  # literal => eax
21866     3d/compare-eax-and 0/imm32/false
21867     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
21868 $check-mu-numberlike-arg:check-addr:
21869     # if t is an addr and v is dereferenced, return whether t->payload is an addr
21870     {
21871       (mu-addr-type? %esi)  # => eax
21872       3d/compare-eax-and 0/imm32/false
21873       74/jump-if-= break/disp8
21874       8b/-> *(ebp+8) 0/r32/eax
21875       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
21876       3d/compare-eax-and 0/imm32/false
21877       {
21878         74/jump-if-= break/disp8
21879         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
21880         # if t->right is null, t = t->left
21881         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21882         {
21883           75/jump-if-!= break/disp8
21884           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21885         }
21886         (mu-addr-type? %eax)  # => eax
21887         3d/compare-eax-and 0/imm32/false
21888         74/jump-if-= $check-mu-numberlike-arg:end/disp8
21889       }
21890     }
21891 $check-mu-numberlike-arg:output-checks:
21892     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
21893 $check-mu-numberlike-arg:end:
21894     # . restore registers
21895     5e/pop-to-esi
21896     58/pop-to-eax
21897     # . epilogue
21898     89/<- %esp 5/r32/ebp
21899     5d/pop-to-ebp
21900     c3/return
21901 
21902 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21903     # . prologue
21904     55/push-ebp
21905     89/<- %ebp 4/r32/esp
21906     # . save registers
21907     50/push-eax
21908     #
21909     (mu-numberlike-output-var? *(ebp+8))  # => eax
21910     3d/compare-eax-and 0/imm32/false
21911     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
21912 $check-mu-numberlike-output:end:
21913     # . restore registers
21914     58/pop-to-eax
21915     # . epilogue
21916     89/<- %esp 5/r32/ebp
21917     5d/pop-to-ebp
21918     c3/return
21919 
21920 $check-mu-numberlike-output:fail:
21921     # otherwise raise an error
21922     (write-buffered *(ebp+0x14) "fn ")
21923     8b/-> *(ebp+0x10) 0/r32/eax
21924     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21925     (write-buffered *(ebp+0x14) %eax)
21926     (write-buffered *(ebp+0x14) ": stmt ")
21927     8b/-> *(ebp+0xc) 0/r32/eax
21928     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21929     (write-buffered *(ebp+0x14) %eax)
21930     (write-buffered *(ebp+0x14) ": '")
21931     8b/-> *(ebp+8) 0/r32/eax
21932     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21933     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21934     (write-buffered *(ebp+0x14) %eax)
21935     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
21936     (flush *(ebp+0x14))
21937     (stop *(ebp+0x18) 1)
21938     # never gets here
21939 
21940 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
21941     # . prologue
21942     55/push-ebp
21943     89/<- %ebp 4/r32/esp
21944     #
21945     8b/-> *(ebp+8) 0/r32/eax
21946     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21947     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21948     (mu-numberlike-output? %eax)  # => eax
21949 $mu-numberlike-output-var?:end:
21950     # . epilogue
21951     89/<- %esp 5/r32/ebp
21952     5d/pop-to-ebp
21953     c3/return
21954 
21955 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
21956     # . prologue
21957     55/push-ebp
21958     89/<- %ebp 4/r32/esp
21959     # . save registers
21960     56/push-esi
21961     # var t/esi: (addr type-tree) = lookup(v->value->type)
21962     8b/-> *(ebp+8) 6/r32/esi
21963 $mu-numberlike-output?:check-int:
21964     # if t is an int, return
21965     (simple-mu-type? %esi 1)  # int => eax
21966     3d/compare-eax-and 0/imm32/false
21967     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
21968 $mu-numberlike-output?:check-float:
21969     # if t is a float, return
21970     (simple-mu-type? %esi 0xf)  # float => eax
21971     3d/compare-eax-and 0/imm32/false
21972     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21973 $mu-numberlike-output?:check-boolean:
21974     # if t is a boolean, return
21975     (simple-mu-type? %esi 5)  # boolean => eax
21976     3d/compare-eax-and 0/imm32/false
21977     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21978 $mu-numberlike-output?:check-byte:
21979     # if t is a byte, return
21980     (simple-mu-type? %esi 8)  # byte => eax
21981     3d/compare-eax-and 0/imm32/false
21982     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21983 $mu-numberlike-output?:check-code-point:
21984     # if t is a code-point, return
21985     (simple-mu-type? %esi 0xd)  # code-point => eax
21986     3d/compare-eax-and 0/imm32/false
21987     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21988 $mu-numberlike-output?:check-grapheme:
21989     # if t is a grapheme, return
21990     (simple-mu-type? %esi 0xe)  # grapheme => eax
21991     3d/compare-eax-and 0/imm32/false
21992     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
21993 $mu-numberlike-output?:return-false:
21994     b8/copy-to-eax 0/imm32/false
21995     eb/jump $mu-numberlike-output?:end/disp8
21996 $mu-numberlike-output?:return-true:
21997     b8/copy-to-eax 1/imm32/true
21998 $mu-numberlike-output?:end:
21999     # . restore registers
22000     5e/pop-to-esi
22001     # . epilogue
22002     89/<- %esp 5/r32/ebp
22003     5d/pop-to-ebp
22004     c3/return
22005 
22006 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22007     # . prologue
22008     55/push-ebp
22009     89/<- %ebp 4/r32/esp
22010     # . save registers
22011     50/push-eax
22012     51/push-ecx
22013     52/push-edx
22014     56/push-esi
22015     57/push-edi
22016     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22017     81 5/subop/subtract %esp 0x60/imm32
22018     68/push 0x60/imm32/size
22019     68/push 0/imm32/read
22020     68/push 0/imm32/write
22021     89/<- %edx 4/r32/esp
22022 $check-mu-copy-stmt:get-output:
22023     # esi = stmt
22024     8b/-> *(ebp+8) 6/r32/esi
22025     # var output/edi: (addr stmt-var) = stmt->outputs
22026     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22027     89/<- %edi 0/r32/eax
22028     # zero outputs
22029     3d/compare-eax-and 0/imm32
22030     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
22031     # > 1 output
22032     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22033     3d/compare-eax-and 0/imm32
22034     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
22035 $check-mu-copy-stmt:get-inout:
22036     # var inout/esi: (addr stmt-var) = stmt->inouts
22037     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22038     89/<- %esi 0/r32/eax
22039     # zero inouts
22040     3d/compare-eax-and 0/imm32
22041     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
22042     # > 1 inout
22043     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22044     3d/compare-eax-and 0/imm32
22045     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
22046 $check-mu-copy-stmt:types:
22047     # if inout is not a scalar, abort
22048     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22049     (size-of %eax)  # => eax
22050     3d/compare-eax-and 4/imm32
22051     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
22052     # var inout-type/ecx: (addr type-tree) = inout->value->type
22053     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22054     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22055     89/<- %ecx 0/r32/eax
22056     # if (inout->is-deref?) inout-type = inout-type->payload
22057     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22058     3d/compare-eax-and 0/imm32/false
22059     {
22060       74/jump-if-= break/disp8
22061       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22062       # if inout-type->right is null, t = inout-type->left
22063       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22064       {
22065         75/jump-if-!= break/disp8
22066         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22067       }
22068       89/<- %ecx 0/r32/eax
22069     }
22070     # if output not in register, abort
22071     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22072     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22073     3d/compare-eax-and 0/imm32
22074     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
22075     # var output-type/eax: (addr type-tree) = output->value->type
22076     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22077     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22078     # if (inout-type == output-type) return
22079     (type-match? %eax %ecx %edx)  # => eax
22080     3d/compare-eax-and 0/imm32
22081     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
22082     # if output is an addr and inout is 0, return
22083     {
22084       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22085       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22086       (mu-addr-type? %eax)  # => eax
22087       3d/compare-eax-and 0/imm32/false
22088       74/jump-if-= break/disp8
22089       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22090       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22091       (string-equal? %eax "0")  # => eax
22092       3d/compare-eax-and 0/imm32/false
22093       74/jump-if-= break/disp8
22094       e9/jump $check-mu-copy-stmt:end/disp32
22095     }
22096     # if output is an offset and inout is 0, return
22097     {
22098       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22099       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22100       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
22101       75/jump-if-!= break/disp8
22102       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22103       (simple-mu-type? %eax 7)  # offset => eax
22104       3d/compare-eax-and 0/imm32/false
22105       74/jump-if-= break/disp8
22106       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22107       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22108       (string-equal? %eax "0")  # => eax
22109       3d/compare-eax-and 0/imm32/false
22110       74/jump-if-= break/disp8
22111       e9/jump $check-mu-copy-stmt:end/disp32
22112     }
22113     # if output is a byte, abort if inout is not a literal. Otherwise return.
22114     {
22115       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22116       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22117       (simple-mu-type? %eax 8)  # byte => eax
22118       3d/compare-eax-and 0/imm32/false
22119       74/jump-if-= break/disp8
22120       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22121       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22122       (simple-mu-type? %eax 0)  # literal => eax
22123       3d/compare-eax-and 0/imm32/false
22124       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
22125       eb/jump $check-mu-copy-stmt:end/disp8
22126     }
22127     # if output is not number-like, abort
22128     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22129 $check-mu-copy-stmt:end:
22130     # . reclaim locals
22131     81 0/subop/add %esp 0x6c/imm32
22132     # . restore registers
22133     5f/pop-to-edi
22134     5e/pop-to-esi
22135     5a/pop-to-edx
22136     59/pop-to-ecx
22137     58/pop-to-eax
22138     # . epilogue
22139     89/<- %esp 5/r32/ebp
22140     5d/pop-to-ebp
22141     c3/return
22142 
22143 $check-mu-copy-stmt:error-no-inout:
22144     (write-buffered *(ebp+0x10) "fn ")
22145     8b/-> *(ebp+0xc) 0/r32/eax
22146     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22147     (write-buffered *(ebp+0x10) %eax)
22148     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
22149     (flush *(ebp+0x10))
22150     (stop *(ebp+0x14) 1)
22151     # never gets here
22152 
22153 $check-mu-copy-stmt:error-too-many-inouts:
22154     (write-buffered *(ebp+0x10) "fn ")
22155     8b/-> *(ebp+0xc) 0/r32/eax
22156     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22157     (write-buffered *(ebp+0x10) %eax)
22158     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
22159     (flush *(ebp+0x10))
22160     (stop *(ebp+0x14) 1)
22161     # never gets here
22162 
22163 $check-mu-copy-stmt:error-no-output:
22164     (write-buffered *(ebp+0x10) "fn ")
22165     8b/-> *(ebp+0xc) 0/r32/eax
22166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22167     (write-buffered *(ebp+0x10) %eax)
22168     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
22169     (flush *(ebp+0x10))
22170     (stop *(ebp+0x14) 1)
22171     # never gets here
22172 
22173 $check-mu-copy-stmt:error-output-not-in-register:
22174     (write-buffered *(ebp+0x10) "fn ")
22175     8b/-> *(ebp+0xc) 0/r32/eax
22176     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22177     (write-buffered *(ebp+0x10) %eax)
22178     (write-buffered *(ebp+0x10) ": stmt copy: output '")
22179     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22180     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22181     (write-buffered *(ebp+0x10) %eax)
22182     (write-buffered *(ebp+0x10) "' not in a register\n")
22183     (flush *(ebp+0x10))
22184     (stop *(ebp+0x14) 1)
22185     # never gets here
22186 
22187 $check-mu-copy-stmt:error-too-many-outputs:
22188     (write-buffered *(ebp+0x10) "fn ")
22189     8b/-> *(ebp+0xc) 0/r32/eax
22190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22191     (write-buffered *(ebp+0x10) %eax)
22192     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
22193     (flush *(ebp+0x10))
22194     (stop *(ebp+0x14) 1)
22195     # never gets here
22196 
22197 $check-mu-copy-stmt:error-inout-too-large:
22198     (write-buffered *(ebp+0x10) "fn ")
22199     8b/-> *(ebp+0xc) 0/r32/eax
22200     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22201     (write-buffered *(ebp+0x10) %eax)
22202     (write-buffered *(ebp+0x10) ": stmt copy: '")
22203     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22204     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22205     (write-buffered *(ebp+0x10) %eax)
22206     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22207     (flush *(ebp+0x10))
22208     (stop *(ebp+0x14) 1)
22209     # never gets here
22210 
22211 $check-mu-copy-stmt:error-non-literal-to-byte:
22212     (write-buffered *(ebp+0x10) "fn ")
22213     8b/-> *(ebp+0xc) 0/r32/eax
22214     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22215     (write-buffered *(ebp+0x10) %eax)
22216     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
22217     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22218     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22219     (write-buffered *(ebp+0x10) %eax)
22220     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
22221     (flush *(ebp+0x10))
22222     (stop *(ebp+0x14) 1)
22223     # never gets here
22224 
22225 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22226     # . prologue
22227     55/push-ebp
22228     89/<- %ebp 4/r32/esp
22229     # . save registers
22230     50/push-eax
22231     51/push-ecx
22232     52/push-edx
22233     53/push-ebx
22234     56/push-esi
22235     57/push-edi
22236     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22237     81 5/subop/subtract %esp 0x60/imm32
22238     68/push 0x60/imm32/size
22239     68/push 0/imm32/read
22240     68/push 0/imm32/write
22241     89/<- %edx 4/r32/esp
22242     # esi = stmt
22243     8b/-> *(ebp+8) 6/r32/esi
22244 $check-mu-copy-to-stmt:check-for-output:
22245     # if stmt->outputs abort
22246     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22247     3d/compare-eax-and 0/imm32
22248     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
22249 $check-mu-copy-to-stmt:get-dest:
22250     # var dest/edi: (addr stmt-var) = stmt->inouts
22251     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22252     89/<- %edi 0/r32/eax
22253     # zero inouts
22254     3d/compare-eax-and 0/imm32
22255     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22256 $check-mu-copy-to-stmt:get-src:
22257     # var src/esi: (addr stmt-var) = dest->next
22258     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22259     89/<- %esi 0/r32/eax
22260     # 1 inout
22261     3d/compare-eax-and 0/imm32
22262     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22263     # > 2 inouts
22264     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22265     3d/compare-eax-and 0/imm32
22266     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
22267 $check-mu-copy-to-stmt:types:
22268     # if src is not a scalar, abort
22269     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22270     (size-of %eax)  # => eax
22271     3d/compare-eax-and 4/imm32
22272     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
22273     # var src-type/ecx: (addr type-tree) = src->value->type
22274     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22275     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22276     89/<- %ecx 0/r32/eax
22277     # if src not in register or literal, abort
22278     # (we can't use stack-offset because it hasn't been computed yet)
22279     {
22280       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22281       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22282       (simple-mu-type? %eax 0)  # => eax
22283       3d/compare-eax-and 0/imm32
22284       75/jump-if-!= break/disp8
22285       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22286       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22287       3d/compare-eax-and 0/imm32
22288       75/jump-if-!= break/disp8
22289       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
22290     }
22291     # var dest-type/ebx: (addr type-tree) = dest->value->type
22292     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22293     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22294     89/<- %ebx 0/r32/eax
22295     # if (dest->is-deref?) dest-type = dest-type->payload
22296 $check-mu-copy-to-stmt:check-dest-deref:
22297     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22298     3d/compare-eax-and 0/imm32/false
22299     {
22300       74/jump-if-= break/disp8
22301       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22302 $check-mu-copy-to-stmt:dest-is-deref:
22303       # if dest-type->right is null, dest-type = dest-type->left
22304       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22305       {
22306         75/jump-if-!= break/disp8
22307 $check-mu-copy-to-stmt:dest-is-deref2:
22308         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22309       }
22310       89/<- %ebx 0/r32/eax
22311     }
22312     # if dest is a byte and src is not a literal, abort
22313     {
22314 $check-mu-copy-to-stmt:final-check-byte:
22315       (simple-mu-type? %ebx 8)  # byte => eax
22316       3d/compare-eax-and 0/imm32/false
22317       74/jump-if-= break/disp8
22318       (simple-mu-type? %ecx 0)  # literal => eax
22319       3d/compare-eax-and 0/imm32/false
22320       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
22321     }
22322     # if (src-type == dest-type) return
22323     (type-match? %ebx %ecx %edx)  # => eax
22324     3d/compare-eax-and 0/imm32
22325     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
22326     # if dest is an addr and src is 0, return
22327     {
22328 $check-mu-copy-to-stmt:final-check-addr:
22329       (mu-addr-type? %ebx)  # => eax
22330       3d/compare-eax-and 0/imm32/false
22331       74/jump-if-= break/disp8
22332       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22333       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22334       (string-equal? %eax "0")  # => eax
22335       3d/compare-eax-and 0/imm32/false
22336       74/jump-if-= break/disp8
22337       e9/jump $check-mu-copy-to-stmt:end/disp32
22338     }
22339     # if dest is an offset and src is 0, return
22340     {
22341 $check-mu-copy-to-stmt:final-check-offset:
22342       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22343       75/jump-if-!= break/disp8
22344       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22345       (simple-mu-type? %eax 7)  # offset => eax
22346       3d/compare-eax-and 0/imm32/false
22347       74/jump-if-= break/disp8
22348       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22349       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22350       (string-equal? %eax "0")  # => eax
22351       3d/compare-eax-and 0/imm32/false
22352       74/jump-if-= break/disp8
22353       e9/jump $check-mu-copy-to-stmt:end/disp32
22354     }
22355     # if dest is not number-like, abort
22356     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22357 $check-mu-copy-to-stmt:end:
22358     # . reclaim locals
22359     81 0/subop/add %esp 0x6c/imm32
22360     # . restore registers
22361     5f/pop-to-edi
22362     5e/pop-to-esi
22363     5b/pop-to-ebx
22364     5a/pop-to-edx
22365     59/pop-to-ecx
22366     58/pop-to-eax
22367     # . epilogue
22368     89/<- %esp 5/r32/ebp
22369     5d/pop-to-ebp
22370     c3/return
22371 
22372 $check-mu-copy-to-stmt:error-incorrect-inouts:
22373     (write-buffered *(ebp+0x10) "fn ")
22374     8b/-> *(ebp+0xc) 0/r32/eax
22375     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22376     (write-buffered *(ebp+0x10) %eax)
22377     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
22378     (flush *(ebp+0x10))
22379     (stop *(ebp+0x14) 1)
22380     # never gets here
22381 
22382 $check-mu-copy-to-stmt:error-too-many-outputs:
22383     (write-buffered *(ebp+0x10) "fn ")
22384     8b/-> *(ebp+0xc) 0/r32/eax
22385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22386     (write-buffered *(ebp+0x10) %eax)
22387     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
22388     (flush *(ebp+0x10))
22389     (stop *(ebp+0x14) 1)
22390     # never gets here
22391 
22392 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
22393     (write-buffered *(ebp+0x10) "fn ")
22394     8b/-> *(ebp+0xc) 0/r32/eax
22395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22396     (write-buffered *(ebp+0x10) %eax)
22397     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
22398     (flush *(ebp+0x10))
22399     (stop *(ebp+0x14) 1)
22400     # never gets here
22401 
22402 $check-mu-copy-to-stmt:error-src-too-large:
22403     (write-buffered *(ebp+0x10) "fn ")
22404     8b/-> *(ebp+0xc) 0/r32/eax
22405     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22406     (write-buffered *(ebp+0x10) %eax)
22407     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
22408     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22409     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22410     (write-buffered *(ebp+0x10) %eax)
22411     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22412     (flush *(ebp+0x10))
22413     (stop *(ebp+0x14) 1)
22414     # never gets here
22415 
22416 $check-mu-copy-to-stmt:error-non-literal-to-byte:
22417     (write-buffered *(ebp+0x10) "fn ")
22418     8b/-> *(ebp+0xc) 0/r32/eax
22419     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22420     (write-buffered *(ebp+0x10) %eax)
22421     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
22422     (flush *(ebp+0x10))
22423     (stop *(ebp+0x14) 1)
22424     # never gets here
22425 
22426 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22427     # . prologue
22428     55/push-ebp
22429     89/<- %ebp 4/r32/esp
22430     # . save registers
22431     50/push-eax
22432     51/push-ecx
22433     52/push-edx
22434     56/push-esi
22435     57/push-edi
22436     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22437     81 5/subop/subtract %esp 0x60/imm32
22438     68/push 0x60/imm32/size
22439     68/push 0/imm32/read
22440     68/push 0/imm32/write
22441     89/<- %edx 4/r32/esp
22442 $check-mu-copy-byte-stmt:get-output:
22443     # esi = stmt
22444     8b/-> *(ebp+8) 6/r32/esi
22445     # var output/edi: (addr stmt-var) = stmt->outputs
22446     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22447     89/<- %edi 0/r32/eax
22448     # zero outputs
22449     3d/compare-eax-and 0/imm32
22450     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
22451     # > 1 output
22452     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22453     3d/compare-eax-and 0/imm32
22454     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
22455 $check-mu-copy-byte-stmt:get-inout:
22456     # var inout/esi: (addr stmt-var) = stmt->inouts
22457     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22458     89/<- %esi 0/r32/eax
22459     # zero inouts
22460     3d/compare-eax-and 0/imm32
22461     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
22462     # > 1 inout
22463     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22464     3d/compare-eax-and 0/imm32
22465     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
22466 $check-mu-copy-byte-stmt:types:
22467     # if inout is not a scalar, abort
22468     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22469     (size-of %eax)  # => eax
22470     3d/compare-eax-and 4/imm32
22471     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
22472     # var inout-type/ecx: (addr type-tree) = inout->value->type
22473     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22474     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22475     89/<- %ecx 0/r32/eax
22476 $check-mu-copy-byte-stmt:check-inout-deref:
22477     # if (inout->is-deref?) inout-type = inout-type->payload
22478     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22479     3d/compare-eax-and 0/imm32/false
22480     {
22481       74/jump-if-= break/disp8
22482 $check-mu-copy-byte-stmt:inout-is-deref:
22483       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22484       # if inout-type->right is null, t = inout-type->left
22485       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22486       {
22487         75/jump-if-!= break/disp8
22488 $check-mu-copy-byte-stmt:inout-is-deref2:
22489         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22490       }
22491       89/<- %ecx 0/r32/eax
22492     }
22493     # if output not in register, abort
22494     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22495     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22496     3d/compare-eax-and 0/imm32
22497     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
22498     # var output-type/eax: (addr type-tree) = output->value->type
22499     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22500     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22501     # if output is not of type byte, abort
22502     (simple-mu-type? %eax 8)  # byte => eax
22503     3d/compare-eax-and 0/imm32
22504     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
22505 $check-mu-copy-byte-stmt:end:
22506     # . reclaim locals
22507     81 0/subop/add %esp 0x6c/imm32
22508     # . restore registers
22509     5f/pop-to-edi
22510     5e/pop-to-esi
22511     5a/pop-to-edx
22512     59/pop-to-ecx
22513     58/pop-to-eax
22514     # . epilogue
22515     89/<- %esp 5/r32/ebp
22516     5d/pop-to-ebp
22517     c3/return
22518 
22519 $check-mu-copy-byte-stmt:error-no-inout:
22520     (write-buffered *(ebp+0x10) "fn ")
22521     8b/-> *(ebp+0xc) 0/r32/eax
22522     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22523     (write-buffered *(ebp+0x10) %eax)
22524     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
22525     (flush *(ebp+0x10))
22526     (stop *(ebp+0x14) 1)
22527     # never gets here
22528 
22529 $check-mu-copy-byte-stmt:error-too-many-inouts:
22530     (write-buffered *(ebp+0x10) "fn ")
22531     8b/-> *(ebp+0xc) 0/r32/eax
22532     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22533     (write-buffered *(ebp+0x10) %eax)
22534     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
22535     (flush *(ebp+0x10))
22536     (stop *(ebp+0x14) 1)
22537     # never gets here
22538 
22539 $check-mu-copy-byte-stmt:error-no-output:
22540     (write-buffered *(ebp+0x10) "fn ")
22541     8b/-> *(ebp+0xc) 0/r32/eax
22542     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22543     (write-buffered *(ebp+0x10) %eax)
22544     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
22545     (flush *(ebp+0x10))
22546     (stop *(ebp+0x14) 1)
22547     # never gets here
22548 
22549 $check-mu-copy-byte-stmt:error-output-not-in-register:
22550     (write-buffered *(ebp+0x10) "fn ")
22551     8b/-> *(ebp+0xc) 0/r32/eax
22552     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22553     (write-buffered *(ebp+0x10) %eax)
22554     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
22555     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22556     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22557     (write-buffered *(ebp+0x10) %eax)
22558     (write-buffered *(ebp+0x10) "' not in a register\n")
22559     (flush *(ebp+0x10))
22560     (stop *(ebp+0x14) 1)
22561     # never gets here
22562 
22563 $check-mu-copy-byte-stmt:error-too-many-outputs:
22564     (write-buffered *(ebp+0x10) "fn ")
22565     8b/-> *(ebp+0xc) 0/r32/eax
22566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22567     (write-buffered *(ebp+0x10) %eax)
22568     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
22569     (flush *(ebp+0x10))
22570     (stop *(ebp+0x14) 1)
22571     # never gets here
22572 
22573 $check-mu-copy-byte-stmt:error-invalid-output-type:
22574     (write-buffered *(ebp+0x10) "fn ")
22575     8b/-> *(ebp+0xc) 0/r32/eax
22576     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22577     (write-buffered *(ebp+0x10) %eax)
22578     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
22579     (flush *(ebp+0x10))
22580     (stop *(ebp+0x14) 1)
22581     # never gets here
22582 
22583 $check-mu-copy-byte-stmt:error-inout-too-large:
22584     (write-buffered *(ebp+0x10) "fn ")
22585     8b/-> *(ebp+0xc) 0/r32/eax
22586     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22587     (write-buffered *(ebp+0x10) %eax)
22588     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
22589     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22590     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22591     (write-buffered *(ebp+0x10) %eax)
22592     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
22593     (flush *(ebp+0x10))
22594     (stop *(ebp+0x14) 1)
22595     # never gets here
22596 
22597 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22598     # . prologue
22599     55/push-ebp
22600     89/<- %ebp 4/r32/esp
22601     # . save registers
22602     50/push-eax
22603     52/push-edx
22604     53/push-ebx
22605     56/push-esi
22606     57/push-edi
22607     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22608     81 5/subop/subtract %esp 0x60/imm32
22609     68/push 0x60/imm32/size
22610     68/push 0/imm32/read
22611     68/push 0/imm32/write
22612     89/<- %edx 4/r32/esp
22613     # esi = stmt
22614     8b/-> *(ebp+8) 6/r32/esi
22615 $check-mu-copy-byte-to-stmt:check-for-output:
22616     # if stmt->outputs abort
22617     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22618     3d/compare-eax-and 0/imm32
22619     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
22620 $check-mu-copy-byte-to-stmt:get-dest:
22621     # var dest/edi: (addr stmt-var) = stmt->inouts
22622     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22623     89/<- %edi 0/r32/eax
22624     # zero inouts
22625     3d/compare-eax-and 0/imm32
22626     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22627 $check-mu-copy-byte-to-stmt:get-src:
22628     # var src/esi: (addr stmt-var) = dest->next
22629     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22630     89/<- %esi 0/r32/eax
22631     # 1 inout
22632     3d/compare-eax-and 0/imm32
22633     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22634     # > 2 inouts
22635     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22636     3d/compare-eax-and 0/imm32
22637     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
22638 $check-mu-copy-byte-to-stmt:types:
22639     # if src is not a scalar, abort
22640     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22641     (size-of %eax)  # => eax
22642     3d/compare-eax-and 4/imm32
22643     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
22644     # if src not in register, abort
22645     {
22646       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22647       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22648       3d/compare-eax-and 0/imm32
22649       75/jump-if-!= break/disp8
22650       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
22651     }
22652     # var dest-type/ebx: (addr type-tree) = dest->value->type
22653     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22654     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22655     89/<- %ebx 0/r32/eax
22656     # if (dest->is-deref?) dest-type = dest-type->payload
22657 $check-mu-copy-byte-to-stmt:check-dest-deref:
22658     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22659     3d/compare-eax-and 0/imm32/false
22660     {
22661       74/jump-if-= break/disp8
22662       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22663 $check-mu-copy-byte-to-stmt:dest-is-deref:
22664       # if dest-type->right is null, dest-type = dest-type->left
22665       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22666       {
22667         75/jump-if-!= break/disp8
22668 $check-mu-copy-byte-to-stmt:dest-is-deref2:
22669         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22670       }
22671       89/<- %ebx 0/r32/eax
22672     }
22673     # if dest is not a byte, abort
22674     (simple-mu-type? %ebx 8)  # byte => eax
22675     3d/compare-eax-and 0/imm32/false
22676     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
22677 $check-mu-copy-byte-to-stmt:end:
22678     # . reclaim locals
22679     81 0/subop/add %esp 0x6c/imm32
22680     # . restore registers
22681     5f/pop-to-edi
22682     5e/pop-to-esi
22683     5b/pop-to-ebx
22684     5a/pop-to-edx
22685     58/pop-to-eax
22686     # . epilogue
22687     89/<- %esp 5/r32/ebp
22688     5d/pop-to-ebp
22689     c3/return
22690 
22691 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
22692     (write-buffered *(ebp+0x10) "fn ")
22693     8b/-> *(ebp+0xc) 0/r32/eax
22694     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22695     (write-buffered *(ebp+0x10) %eax)
22696     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
22697     (flush *(ebp+0x10))
22698     (stop *(ebp+0x14) 1)
22699     # never gets here
22700 
22701 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
22702     (write-buffered *(ebp+0x10) "fn ")
22703     8b/-> *(ebp+0xc) 0/r32/eax
22704     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22705     (write-buffered *(ebp+0x10) %eax)
22706     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
22707     (flush *(ebp+0x10))
22708     (stop *(ebp+0x14) 1)
22709     # never gets here
22710 
22711 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
22712     (write-buffered *(ebp+0x10) "fn ")
22713     8b/-> *(ebp+0xc) 0/r32/eax
22714     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22715     (write-buffered *(ebp+0x10) %eax)
22716     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
22717     (flush *(ebp+0x10))
22718     (stop *(ebp+0x14) 1)
22719     # never gets here
22720 
22721 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
22722     (write-buffered *(ebp+0x10) "fn ")
22723     8b/-> *(ebp+0xc) 0/r32/eax
22724     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22725     (write-buffered *(ebp+0x10) %eax)
22726     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22727     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22728     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22729     (write-buffered *(ebp+0x10) %eax)
22730     (write-buffered *(ebp+0x10) "' must be a byte\n")
22731     (flush *(ebp+0x10))
22732     (stop *(ebp+0x14) 1)
22733     # never gets here
22734 
22735 $check-mu-copy-byte-to-stmt:error-src-too-large:
22736     (write-buffered *(ebp+0x10) "fn ")
22737     8b/-> *(ebp+0xc) 0/r32/eax
22738     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22739     (write-buffered *(ebp+0x10) %eax)
22740     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
22741     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22742     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22743     (write-buffered *(ebp+0x10) %eax)
22744     (write-buffered *(ebp+0x10) "' is too large to copy\n")
22745     (flush *(ebp+0x10))
22746     (stop *(ebp+0x14) 1)
22747     # never gets here
22748 
22749 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22750     # . prologue
22751     55/push-ebp
22752     89/<- %ebp 4/r32/esp
22753     # . save registers
22754     50/push-eax
22755     51/push-ecx
22756     52/push-edx
22757     53/push-ebx
22758     56/push-esi
22759     57/push-edi
22760     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
22761     81 5/subop/subtract %esp 0x60/imm32
22762     68/push 0x60/imm32/size
22763     68/push 0/imm32/read
22764     68/push 0/imm32/write
22765     89/<- %edx 4/r32/esp
22766     # esi = stmt
22767     8b/-> *(ebp+8) 6/r32/esi
22768 $check-mu-compare-stmt:check-for-output:
22769     # if stmt->outputs abort
22770     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22771     3d/compare-eax-and 0/imm32
22772     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
22773 $check-mu-compare-stmt:get-left:
22774     # var left/edi: (addr stmt-var) = stmt->inouts
22775     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22776     89/<- %edi 0/r32/eax
22777     # zero inouts
22778     3d/compare-eax-and 0/imm32
22779     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22780 $check-mu-compare-stmt:get-right:
22781     # var right/esi: (addr stmt-var) = left->next
22782     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22783     89/<- %esi 0/r32/eax
22784     # 1 inout
22785     3d/compare-eax-and 0/imm32
22786     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22787     # > 2 inouts
22788     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22789     3d/compare-eax-and 0/imm32
22790     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
22791     # if both inouts are in memory, abort
22792     {
22793 $check-mu-compare-stmt:both-in-mem:
22794       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22795       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22796       (simple-mu-type? %eax 0)  # => eax
22797       3d/compare-eax-and 0/imm32
22798       0f 85/jump-if-!= break/disp32
22799       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22800       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22801       3d/compare-eax-and 0/imm32
22802       75/jump-if-!= break/disp8
22803       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22804       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
22805       (simple-mu-type? %eax 0)  # => eax
22806       3d/compare-eax-and 0/imm32
22807       75/jump-if-!= break/disp8
22808       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22809       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22810       3d/compare-eax-and 0/imm32
22811       75/jump-if-!= break/disp8
22812       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
22813     }
22814 $check-mu-compare-stmt:types:
22815     # var right-type/ecx: (addr type-tree) = right->value->type
22816     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22817     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22818     89/<- %ecx 0/r32/eax
22819     # if (right->is-deref?) right-type = right-type->payload
22820     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
22821     3d/compare-eax-and 0/imm32/false
22822     {
22823       74/jump-if-= break/disp8
22824       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
22825       # if right-type->right is null, right-type = right-type->left
22826       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22827       {
22828         75/jump-if-!= break/disp8
22829         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22830       }
22831       89/<- %ecx 0/r32/eax
22832     }
22833     # if right-type is a literal string, abort
22834     (simple-mu-type? %ecx 0x10)  # string-literal => eax
22835     3d/compare-eax-and 0/imm32/false
22836     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
22837     # if right is not a scalar, abort
22838     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22839     (size-of %eax)  # => eax
22840     3d/compare-eax-and 4/imm32
22841     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
22842     # if left is not a scalar, abort
22843     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22844     (size-of %eax)  # => eax
22845     3d/compare-eax-and 4/imm32
22846     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
22847     # var left-type/ebx: (addr type-tree) = left->value->type
22848     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22849     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22850     89/<- %ebx 0/r32/eax
22851     # if (left->is-deref?) left-type = left-type->payload
22852     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
22853     3d/compare-eax-and 0/imm32/false
22854     {
22855       74/jump-if-= break/disp8
22856       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22857       # if left-type->right is null, left-type = left-type->left
22858       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
22859       {
22860         75/jump-if-!= break/disp8
22861         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22862       }
22863       89/<- %ebx 0/r32/eax
22864     }
22865     # if (left-type == right-type) return
22866     (type-match? %ebx %ecx %edx)  # => eax
22867     3d/compare-eax-and 0/imm32
22868     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
22869     # if left is an addr and right is 0, return
22870     {
22871       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22872       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22873       (mu-addr-type? %eax)  # => eax
22874       3d/compare-eax-and 0/imm32/false
22875       74/jump-if-= break/disp8
22876       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22877       (lookup *eax *(eax+4))  # Var-name Var-name => eax
22878       (string-equal? %eax "0")  # => eax
22879       3d/compare-eax-and 0/imm32/false
22880       74/jump-if-= break/disp8
22881       eb/jump $check-mu-compare-stmt:end/disp8
22882     }
22883     # if left is not number-like, abort
22884     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
22885 $check-mu-compare-stmt:end:
22886     # . reclaim locals
22887     81 0/subop/add %esp 0x6c/imm32
22888     # . restore registers
22889     5f/pop-to-edi
22890     5e/pop-to-esi
22891     5b/pop-to-ebx
22892     5a/pop-to-edx
22893     59/pop-to-ecx
22894     58/pop-to-eax
22895     # . epilogue
22896     89/<- %esp 5/r32/ebp
22897     5d/pop-to-ebp
22898     c3/return
22899 
22900 $check-mu-compare-stmt:error-incorrect-inouts:
22901     (write-buffered *(ebp+0x10) "fn ")
22902     8b/-> *(ebp+0xc) 0/r32/eax
22903     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22904     (write-buffered *(ebp+0x10) %eax)
22905     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
22906     (flush *(ebp+0x10))
22907     (stop *(ebp+0x14) 1)
22908     # never gets here
22909 
22910 $check-mu-compare-stmt:error-too-many-outputs:
22911     (write-buffered *(ebp+0x10) "fn ")
22912     8b/-> *(ebp+0xc) 0/r32/eax
22913     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22914     (write-buffered *(ebp+0x10) %eax)
22915     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
22916     (flush *(ebp+0x10))
22917     (stop *(ebp+0x14) 1)
22918     # never gets here
22919 
22920 $check-mu-compare-stmt:error-both-in-memory:
22921     (write-buffered *(ebp+0x10) "fn ")
22922     8b/-> *(ebp+0xc) 0/r32/eax
22923     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22924     (write-buffered *(ebp+0x10) %eax)
22925     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
22926     (flush *(ebp+0x10))
22927     (stop *(ebp+0x14) 1)
22928     # never gets here
22929 
22930 $check-mu-compare-stmt:error-left-too-large:
22931     (write-buffered *(ebp+0x10) "fn ")
22932     8b/-> *(ebp+0xc) 0/r32/eax
22933     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22934     (write-buffered *(ebp+0x10) %eax)
22935     (write-buffered *(ebp+0x10) ": stmt compare: '")
22936     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
22937     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22938     (write-buffered *(ebp+0x10) %eax)
22939     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22940     (flush *(ebp+0x10))
22941     (stop *(ebp+0x14) 1)
22942     # never gets here
22943 
22944 $check-mu-compare-stmt:error-right-too-large:
22945     (write-buffered *(ebp+0x10) "fn ")
22946     8b/-> *(ebp+0xc) 0/r32/eax
22947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22948     (write-buffered *(ebp+0x10) %eax)
22949     (write-buffered *(ebp+0x10) ": stmt compare: '")
22950     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22951     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22952     (write-buffered *(ebp+0x10) %eax)
22953     (write-buffered *(ebp+0x10) "' is too large to compare\n")
22954     (flush *(ebp+0x10))
22955     (stop *(ebp+0x14) 1)
22956     # never gets here
22957 
22958 $check-mu-compare-stmt:error-right-string-literal:
22959     (write-buffered *(ebp+0x10) "fn ")
22960     8b/-> *(ebp+0xc) 0/r32/eax
22961     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22962     (write-buffered *(ebp+0x10) %eax)
22963     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
22964     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22965     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22966     (write-buffered *(ebp+0x10) %eax)
22967     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
22968     (flush *(ebp+0x10))
22969     (stop *(ebp+0x14) 1)
22970     # never gets here
22971 
22972 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22973     # . prologue
22974     55/push-ebp
22975     89/<- %ebp 4/r32/esp
22976     # . save registers
22977     50/push-eax
22978     51/push-ecx
22979     52/push-edx
22980     56/push-esi
22981     57/push-edi
22982 $check-mu-address-stmt:get-output:
22983     # esi = stmt
22984     8b/-> *(ebp+8) 6/r32/esi
22985     # var output/edi: (addr stmt-var) = stmt->outputs
22986     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22987     89/<- %edi 0/r32/eax
22988     # zero outputs
22989     3d/compare-eax-and 0/imm32
22990     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
22991     # > 1 output
22992     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22993     3d/compare-eax-and 0/imm32
22994     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
22995 $check-mu-address-stmt:get-inout:
22996     # var inout/esi: (addr stmt-var) = stmt->inouts
22997     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22998     89/<- %esi 0/r32/eax
22999     # zero inouts
23000     3d/compare-eax-and 0/imm32
23001     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
23002     # > 1 inout
23003     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23004     3d/compare-eax-and 0/imm32
23005     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
23006 $check-mu-address-stmt:types:
23007     # if output not in register, abort
23008     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23009     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23010     3d/compare-eax-and 0/imm32
23011     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
23012     # var output-type/edx: (addr type-tree) = output->value->type
23013     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23014     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23015     89/<- %edx 0/r32/eax
23016     # if output-type not an addr, abort
23017     (mu-addr-type? %edx)  # => eax
23018     3d/compare-eax-and 0/imm32/false
23019     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
23020     # output-type = output-type->right
23021     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
23022     # if output-type->right is null, output-type = output-type->left
23023     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23024     {
23025       75/jump-if-!= break/disp8
23026       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23027     }
23028     89/<- %edx 0/r32/eax
23029     # var inout-type/ecx: (addr type-tree) = inout->value->type
23030     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23031     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23032     89/<- %ecx 0/r32/eax
23033     # if (inout->is-deref?) inout-type = inout-type->payload
23034     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
23035     3d/compare-eax-and 0/imm32/false
23036     {
23037       74/jump-if-= break/disp8
23038       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23039       # if inout-type->right is null, t = inout-type->left
23040       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23041       {
23042         75/jump-if-!= break/disp8
23043         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23044       }
23045       89/<- %ecx 0/r32/eax
23046     }
23047     # if (inout-type != output-type) abort
23048     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
23049     3d/compare-eax-and 0/imm32
23050     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
23051 $check-mu-address-stmt:end:
23052     # . restore registers
23053     5f/pop-to-edi
23054     5e/pop-to-esi
23055     5a/pop-to-edx
23056     59/pop-to-ecx
23057     58/pop-to-eax
23058     # . epilogue
23059     89/<- %esp 5/r32/ebp
23060     5d/pop-to-ebp
23061     c3/return
23062 
23063 $check-mu-address-stmt:error-no-inout:
23064     (write-buffered *(ebp+0x10) "fn ")
23065     8b/-> *(ebp+0xc) 0/r32/eax
23066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23067     (write-buffered *(ebp+0x10) %eax)
23068     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
23069     (flush *(ebp+0x10))
23070     (stop *(ebp+0x14) 1)
23071     # never gets here
23072 
23073 $check-mu-address-stmt:error-too-many-inouts:
23074     (write-buffered *(ebp+0x10) "fn ")
23075     8b/-> *(ebp+0xc) 0/r32/eax
23076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23077     (write-buffered *(ebp+0x10) %eax)
23078     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
23079     (flush *(ebp+0x10))
23080     (stop *(ebp+0x14) 1)
23081     # never gets here
23082 
23083 $check-mu-address-stmt:error-no-output:
23084     (write-buffered *(ebp+0x10) "fn ")
23085     8b/-> *(ebp+0xc) 0/r32/eax
23086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23087     (write-buffered *(ebp+0x10) %eax)
23088     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
23089     (flush *(ebp+0x10))
23090     (stop *(ebp+0x14) 1)
23091     # never gets here
23092 
23093 $check-mu-address-stmt:error-output-not-in-register:
23094     (write-buffered *(ebp+0x10) "fn ")
23095     8b/-> *(ebp+0xc) 0/r32/eax
23096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23097     (write-buffered *(ebp+0x10) %eax)
23098     (write-buffered *(ebp+0x10) ": stmt address: output '")
23099     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23100     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23101     (write-buffered *(ebp+0x10) %eax)
23102     (write-buffered *(ebp+0x10) "' not in a register\n")
23103     (flush *(ebp+0x10))
23104     (stop *(ebp+0x14) 1)
23105     # never gets here
23106 
23107 $check-mu-address-stmt:error-too-many-outputs:
23108     (write-buffered *(ebp+0x10) "fn ")
23109     8b/-> *(ebp+0xc) 0/r32/eax
23110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23111     (write-buffered *(ebp+0x10) %eax)
23112     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
23113     (flush *(ebp+0x10))
23114     (stop *(ebp+0x14) 1)
23115     # never gets here
23116 
23117 $check-mu-address-stmt:error-output-not-address:
23118     (write-buffered *(ebp+0x10) "fn ")
23119     8b/-> *(ebp+0xc) 0/r32/eax
23120     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23121     (write-buffered *(ebp+0x10) %eax)
23122     (write-buffered *(ebp+0x10) ": stmt address: output '")
23123     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23124     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23125     (write-buffered *(ebp+0x10) %eax)
23126     (write-buffered *(ebp+0x10) "' is not an addr\n")
23127     (flush *(ebp+0x10))
23128     (stop *(ebp+0x14) 1)
23129     # never gets here
23130 
23131 $check-mu-address-stmt:error-type-mismatch:
23132     (write-buffered *(ebp+0x10) "fn ")
23133     8b/-> *(ebp+0xc) 0/r32/eax
23134     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23135     (write-buffered *(ebp+0x10) %eax)
23136     (write-buffered *(ebp+0x10) ": stmt address: output '")
23137     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23138     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23139     (write-buffered *(ebp+0x10) %eax)
23140     (write-buffered *(ebp+0x10) "' cannot hold address of '")
23141     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23142     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23143     (write-buffered *(ebp+0x10) %eax)
23144     (write-buffered *(ebp+0x10) "'\n")
23145     (flush *(ebp+0x10))
23146     (stop *(ebp+0x14) 1)
23147     # never gets here
23148 
23149 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23150     # . prologue
23151     55/push-ebp
23152     89/<- %ebp 4/r32/esp
23153     # . save registers
23154     51/push-ecx
23155     52/push-edx
23156     53/push-ebx
23157     # var curr-a/ecx: (addr type-tree) = a
23158     8b/-> *(ebp+8) 1/r32/ecx
23159     # var curr-b/ebx: (addr type-tree) = b
23160     8b/-> *(ebp+0xc) 3/r32/ebx
23161     # if (curr-a->is-atom?) fall back to regular equality
23162     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
23163     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
23164     # if (curr-a->left != curr-b->left) return false
23165     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
23166     89/<- %edx 0/r32/eax
23167     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23168     (type-equal? %edx %eax)  # => eax
23169     3d/compare-eax-and 0/imm32/false
23170     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
23171     # if (curr-a->left == "array") curr-a = curr-a->element-type
23172     {
23173       (mu-array? %edx)  # => eax
23174       3d/compare-eax-and 0/imm32/false
23175       75/jump-if-!= break/disp8
23176 $type-equal-ignoring-capacity?:array:
23177       # curr-a = curr-a->right->left
23178       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23179       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23180       89/<- %ecx 0/r32/eax
23181       # curr-b = curr-b->right->left
23182       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23183       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23184       89/<- %ebx 0/r32/eax
23185       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23186     }
23187     # if (curr-a->left == "stream") curr-a = curr-a->element-type
23188     {
23189       (mu-stream? %edx)  # => eax
23190       3d/compare-eax-and 0/imm32/false
23191       75/jump-if-!= break/disp8
23192 $type-equal-ignoring-capacity?:stream:
23193       # curr-a = curr-a->right->left
23194       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23195       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23196       89/<- %ecx 0/r32/eax
23197       # curr-b = curr-b->right->left
23198       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23199       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23200       89/<- %ebx 0/r32/eax
23201       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
23202     }
23203 $type-equal-ignoring-capacity?:base-case:
23204     # return type-equal?(curr-a, curr-b)
23205     (type-equal? %ecx %ebx)  # => eax
23206 $type-equal-ignoring-capacity?:end:
23207     # . restore registers
23208     5b/pop-to-ebx
23209     5a/pop-to-edx
23210     59/pop-to-ecx
23211     # . epilogue
23212     89/<- %esp 5/r32/ebp
23213     5d/pop-to-ebp
23214     c3/return
23215 
23216 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23217     # . prologue
23218     55/push-ebp
23219     89/<- %ebp 4/r32/esp
23220     # . save registers
23221     50/push-eax
23222     51/push-ecx
23223     52/push-edx
23224     53/push-ebx
23225     56/push-esi
23226     57/push-edi
23227     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
23228     81 5/subop/subtract %esp 0x60/imm32
23229     68/push 0x60/imm32/size
23230     68/push 0/imm32/read
23231     68/push 0/imm32/write
23232     89/<- %edx 4/r32/esp
23233     # var template/esi: (addr list var) = fn->outputs
23234     8b/-> *(ebp+0xc) 0/r32/eax
23235     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
23236     89/<- %esi 0/r32/eax
23237     # var curr-template/ebx: (addr list var) = fn->outputs
23238     89/<- %ebx 0/r32/eax
23239     # var curr/edi: (addr stmt-var) = stmt->inouts
23240     8b/-> *(ebp+8) 0/r32/eax
23241     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23242     89/<- %edi 0/r32/eax
23243     {
23244       # if template is null, break
23245       81 7/subop/compare %ebx 0/imm32
23246       0f 84/jump-if-= break/disp32
23247       # if curr is null, abort
23248       81 7/subop/compare %edi 0/imm32
23249       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
23250       # var template-type/ecx: (addr type-tree) = template->value->type
23251       (lookup *ebx *(ebx+4))  # List-value List-value => eax
23252       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23253       89/<- %ecx 0/r32/eax
23254       # var curr-type/eax: (addr type-tree) = curr->value->type
23255       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23256       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23257       # if (curr->is-deref?) curr-type = payload of curr-type
23258       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
23259       {
23260         74/jump-if-= break/disp8
23261         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23262         # if t->right is null, t = t->left
23263         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23264         75/jump-if-!= break/disp8
23265         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23266       }
23267       # if curr-type is literal and template-type is float, abort
23268       50/push-eax
23269       {
23270         (simple-mu-type? %eax 0)  # literal => eax
23271         3d/compare-eax-and 0/imm32/false
23272         74/jump-if-= break/disp8
23273         (simple-mu-type? %ecx 0xf)  # float => eax
23274         3d/compare-eax-and 0/imm32/false
23275         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
23276       }
23277       58/pop-to-eax
23278       # if (curr-type != template-type) abort
23279       (type-match? %ecx %eax %edx)  # => eax
23280       3d/compare-eax-and 0/imm32/false
23281       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
23282       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
23283       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
23284       3d/compare-eax-and 0/imm32/false
23285       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
23286       # template = template->next
23287       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
23288       89/<- %ebx 0/r32/eax
23289       # curr = curr->next
23290       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23291       89/<- %edi 0/r32/eax
23292       #
23293       e9/jump loop/disp32
23294     }
23295     # if curr is not null, abort
23296     81 7/subop/compare %edi 0/imm32
23297     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
23298 $check-mu-return-stmt:end:
23299     # . reclaim locals
23300     81 0/subop/add %esp 0x6c/imm32
23301     # . restore registers
23302     5f/pop-to-edi
23303     5e/pop-to-esi
23304     5b/pop-to-ebx
23305     5a/pop-to-edx
23306     59/pop-to-ecx
23307     58/pop-to-eax
23308     # . epilogue
23309     89/<- %esp 5/r32/ebp
23310     5d/pop-to-ebp
23311     c3/return
23312 
23313 $check-mu-return-stmt:error1:
23314     (write-buffered *(ebp+0x10) "fn ")
23315     8b/-> *(ebp+0xc) 0/r32/eax
23316     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23317     (write-buffered *(ebp+0x10) %eax)
23318     (write-buffered *(ebp+0x10) ": return: '")
23319     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23320     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23321     (write-buffered *(ebp+0x10) %eax)
23322     (write-buffered *(ebp+0x10) "' has the wrong type\n")
23323     (flush *(ebp+0x10))
23324     (stop *(ebp+0x14) 1)
23325     # never gets here
23326 
23327 $check-mu-return-stmt:error2:
23328     (write-buffered *(ebp+0x10) "fn ")
23329     8b/-> *(ebp+0xc) 0/r32/eax
23330     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23331     (write-buffered *(ebp+0x10) %eax)
23332     (write-buffered *(ebp+0x10) ": return: '")
23333     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23334     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23335     (write-buffered *(ebp+0x10) %eax)
23336     (write-buffered *(ebp+0x10) "' is no longer available\n")
23337     (flush *(ebp+0x10))
23338     (stop *(ebp+0x14) 1)
23339     # never gets here
23340 
23341 $check-mu-return-stmt:error-literal-to-float:
23342     (write-buffered *(ebp+0x10) "fn ")
23343     8b/-> *(ebp+0xc) 0/r32/eax
23344     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23345     (write-buffered *(ebp+0x10) %eax)
23346     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
23347     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23348     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23349     (write-buffered *(ebp+0x10) %eax)
23350     (write-buffered *(ebp+0x10) "' to float\n")
23351     (flush *(ebp+0x10))
23352     (stop *(ebp+0x14) 1)
23353     # never gets here
23354 
23355 $check-mu-return-stmt:error-too-few-inouts:
23356     (write-buffered *(ebp+0x10) "fn ")
23357     8b/-> *(ebp+0xc) 0/r32/eax
23358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23359     (write-buffered *(ebp+0x10) %eax)
23360     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
23361     (flush *(ebp+0x10))
23362     (stop *(ebp+0x14) 1)
23363     # never gets here
23364 
23365 $check-mu-return-stmt:error-too-many-inouts:
23366     (write-buffered *(ebp+0x10) "fn ")
23367     8b/-> *(ebp+0xc) 0/r32/eax
23368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23369     (write-buffered *(ebp+0x10) %eax)
23370     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
23371     (flush *(ebp+0x10))
23372     (stop *(ebp+0x14) 1)
23373     # never gets here
23374 
23375 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23376     # . prologue
23377     55/push-ebp
23378     89/<- %ebp 4/r32/esp
23379     # . save registers
23380     50/push-eax
23381     51/push-ecx
23382     56/push-esi
23383     # var table/esi: (addr table (handle array byte) int 8)
23384     81 5/subop/subtract %esp 0x60/imm32
23385     68/push 0x60/imm32/size
23386     68/push 0/imm32/read
23387     68/push 0/imm32/write
23388     89/<- %esi 4/r32/esp
23389     # var curr/ecx: (addr list var) = outputs
23390     8b/-> *(ebp+8) 1/r32/ecx
23391     {
23392       # if (curr == 0) break
23393       81 7/subop/compare %ecx 0/imm32
23394       0f 84/jump-if-= break/disp32
23395       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
23396       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23397       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23398       # if reg exists in table, abort
23399       (maybe-get %esi %eax 0xc)  # => eax
23400       3d/compare-eax-and 0/imm32
23401       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
23402       # insert reg in table
23403       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23404       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23405       (get-or-insert %esi %eax 0xc Heap)
23406       # curr = curr->next
23407       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23408       89/<- %ecx 0/r32/eax
23409       e9/jump loop/disp32
23410     }
23411 $check-all-unique-registers:end:
23412     # . reclaim locals
23413     81 0/subop/add %esp 0x6c/imm32
23414     # . restore registers
23415     5e/pop-to-esi
23416     59/pop-to-ecx
23417     58/pop-to-eax
23418     # . epilogue
23419     89/<- %esp 5/r32/ebp
23420     5d/pop-to-ebp
23421     c3/return
23422 
23423 $check-all-unique-registers:abort:
23424     (write-buffered *(ebp+0x10) "fn ")
23425     8b/-> *(ebp+0xc) 0/r32/eax
23426     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23427     (write-buffered *(ebp+0x10) %eax)
23428     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
23429     (flush *(ebp+0x10))
23430     (stop *(ebp+0x14) 1)
23431     # never gets here
23432 
23433 # return false if s's register is not between start (inclusive) and end (exclusive)
23434 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
23435 # otherwise return true
23436 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
23437     # . prologue
23438     55/push-ebp
23439     89/<- %ebp 4/r32/esp
23440     # . save registers
23441     51/push-ecx
23442     52/push-edx
23443     53/push-ebx
23444     56/push-esi
23445     57/push-edi
23446     # var target/ebx: (addr array byte) = s->value->register
23447     8b/-> *(ebp+8) 0/r32/eax
23448     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23449     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23450 #?     (write-buffered Stderr "AA: ")
23451 #?     (write-buffered Stderr %eax)
23452 #?     (write-buffered Stderr Newline)
23453 #?     (flush Stderr)
23454     # if (var->register == 0) return false
23455     3d/compare-eax-and 0/imm32
23456     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
23457     89/<- %ebx 0/r32/eax
23458     # var curr/ecx: (addr list var) = start
23459     8b/-> *(ebp+0xc) 1/r32/ecx
23460     # edx = end
23461     8b/-> *(ebp+0x10) 2/r32/edx
23462     {
23463       # if (curr == 0) break
23464       81 7/subop/compare %edi 0/imm32
23465       0f 84/jump-if-= break/disp32
23466       # if (curr == end) break
23467       39/compare %ecx 2/r32/edx
23468       0f 84/jump-if-= break/disp32
23469       # var curr-reg/eax: (addr array byte) = curr->value->register
23470       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23471       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23472       # if (curr-reg == 0) continue
23473       3d/compare-eax-and 0/imm32
23474       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
23475       # if (curr-reg == target) check for conflict
23476       (string-equal? %eax %ebx)  # => eax
23477       3d/compare-eax-and 0/imm32/false
23478       {
23479         74/jump-if-= break/disp8
23480 #?         (write-buffered Stderr "conflict?\n")
23481 #?         (flush Stderr)
23482         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
23483         8b/-> *(ebp+0x14) 0/r32/eax
23484         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23485         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
23486         eb/jump $register-within-list-with-conflict?:end/disp8
23487       }
23488 $register-within-list-with-conflict?:continue:
23489       # curr = curr->next
23490       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23491       89/<- %ecx 0/r32/eax
23492       e9/jump loop/disp32
23493     }
23494     # return false
23495     b8/copy-to-eax 0/imm32/false
23496 $register-within-list-with-conflict?:end:
23497     # . restore registers
23498     5f/pop-to-edi
23499     5e/pop-to-esi
23500     5b/pop-to-ebx
23501     5a/pop-to-edx
23502     59/pop-to-ecx
23503     # . epilogue
23504     89/<- %esp 5/r32/ebp
23505     5d/pop-to-ebp
23506     c3/return
23507 
23508 # At the first occurrence of register 'reg' in fn-outputs,
23509 # check if the corresponding element of return-inouts has a different register.
23510 # This hacky helper is intended to be called in one specific place. Don't
23511 # reuse it as is.
23512 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
23513     # . prologue
23514     55/push-ebp
23515     89/<- %ebp 4/r32/esp
23516     # . save registers
23517     51/push-ecx
23518     52/push-edx
23519     53/push-ebx
23520     56/push-esi
23521     57/push-edi
23522 #?     (write-buffered Stderr "BB: ")
23523 #?     (write-buffered Stderr *(ebp+8))
23524 #?     (write-buffered Stderr Newline)
23525 #?     (flush Stderr)
23526     # var curr-output/edi: (addr list var) = fn-outputs
23527     8b/-> *(ebp+0x10) 7/r32/edi
23528     # var curr-inout/esi: (addr stmt-var) = return-inouts
23529     8b/-> *(ebp+0xc) 6/r32/esi
23530     {
23531       # if (curr-output == 0) abort
23532       81 7/subop/compare %edi 0/imm32
23533       0f 84/jump-if-= break/disp32
23534       # if (curr-output->value->register != reg) continue
23535       (lookup *edi *(edi+4))  # List-value List-value => eax
23536       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23537       (string-equal? %eax *(ebp+8))  # => eax
23538       3d/compare-eax-and 0/imm32/false
23539       0f 84/jump-if= $register-conflict?:continue/disp32
23540 #?       (write-buffered Stderr "rescan\n")
23541 #?       (flush Stderr)
23542       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
23543       (lookup *esi *(esi+4))  # List-value List-value => eax
23544       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
23545       # if (curr-reg == 0) return true
23546       3d/compare-eax-and 0/imm32
23547       {
23548         75/jump-if-!= break/disp8
23549 #?         (write-buffered Stderr "no register\n")
23550 #?         (flush Stderr)
23551         b8/copy-to-eax 1/imm32/true
23552         e9/jump $register-conflict?:end/disp32
23553       }
23554       # return (curr-reg != reg)
23555       (string-equal? %eax *(ebp+8))  # => eax
23556       3d/compare-eax-and 0/imm32/false
23557       0f 94/set-if-= %al
23558 #?       (write-buffered Stderr "final: ")
23559 #?       (write-int32-hex-buffered Stderr %eax)
23560 #?       (write-buffered Stderr Newline)
23561 #?       (flush Stderr)
23562       eb/jump $register-conflict?:end/disp8
23563 $register-conflict?:continue:
23564       # curr-output = curr-output->next
23565       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23566       89/<- %edi 0/r32/eax
23567       # curr-inout = curr-inout->next
23568       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23569       89/<- %esi 0/r32/eax
23570       e9/jump loop/disp32
23571     }
23572     # should never get here
23573     (write-buffered Stderr "register-conflict? misused\n")
23574     (flush Stderr)
23575     e8/call syscall_exit/disp32
23576 $register-conflict?:end:
23577     # . restore registers
23578     5f/pop-to-edi
23579     5e/pop-to-esi
23580     5b/pop-to-ebx
23581     5a/pop-to-edx
23582     59/pop-to-ecx
23583     # . epilogue
23584     89/<- %esp 5/r32/ebp
23585     5d/pop-to-ebp
23586     c3/return
23587 
23588 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23589     # . prologue
23590     55/push-ebp
23591     89/<- %ebp 4/r32/esp
23592     # . save registers
23593     50/push-eax
23594     51/push-ecx
23595     # var curr/ecx: (addr list stmt) = block->stmts
23596     8b/-> *(ebp+8) 0/r32/eax
23597     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23598     3d/compare-eax-and 0/imm32
23599     74/jump-if-= $check-final-stmt-is-return:error/disp8
23600     89/<- %ecx 0/r32/eax
23601     {
23602       # if curr->next == 0, break
23603       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23604       3d/compare-eax-and 0/imm32
23605       74/jump-if-= break/disp8
23606       # curr = curr->next
23607       89/<- %ecx 0/r32/eax
23608       e9/jump loop/disp32
23609     }
23610 $check-final-stmt-is-return:check-tag:
23611     # if curr->value->tag != Stmt1, abort
23612     (lookup *ecx *(ecx+4))  # List-value List-value => eax
23613     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23614     75/jump-if-!= $check-final-stmt-is-return:error/disp8
23615 $check-final-stmt-is-return:check-operation:
23616     # if curr->operation != "return", abort
23617     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23618     (string-equal? %eax "return")
23619     3d/compare-eax-and 0/imm32/false
23620     74/jump-if-= $check-final-stmt-is-return:error/disp8
23621 $check-final-stmt-is-return:end:
23622     # . restore registers
23623     59/pop-to-ecx
23624     58/pop-to-eax
23625     # . epilogue
23626     89/<- %esp 5/r32/ebp
23627     5d/pop-to-ebp
23628     c3/return
23629 
23630 $check-final-stmt-is-return:error:
23631     (write-buffered *(ebp+0x10) "fn ")
23632     8b/-> *(ebp+0xc) 0/r32/eax
23633     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23634     (write-buffered *(ebp+0x10) %eax)
23635     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
23636     (flush *(ebp+0x10))
23637     (stop *(ebp+0x14) 1)
23638     # never gets here
23639 
23640 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23641     # . prologue
23642     55/push-ebp
23643     89/<- %ebp 4/r32/esp
23644     # . save registers
23645     50/push-eax
23646     51/push-ecx
23647     # var curr/ecx: (addr list stmt) = block->stmts
23648     8b/-> *(ebp+8) 0/r32/eax
23649     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
23650     3d/compare-eax-and 0/imm32
23651     0f 84/jump-if-= $check-no-breaks:end/disp32
23652     89/<- %ecx 0/r32/eax
23653     {
23654       # if curr->next == 0, break
23655       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23656       3d/compare-eax-and 0/imm32
23657       74/jump-if-= break/disp8
23658       # if curr->value->tag != Stmt1, continue
23659       (lookup *ecx *(ecx+4))  # List-value List-value => eax
23660       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
23661       75/jump-if-!= $check-no-breaks:continue/disp8
23662       # if curr->value->operation starts with "break", abort
23663       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23664       (string-starts-with? %eax "break")  # => eax
23665       3d/compare-eax-and 0/imm32/false
23666       75/jump-if-!= $check-no-breaks:error/disp8
23667 $check-no-breaks:continue:
23668       # curr = curr->next
23669       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
23670       89/<- %ecx 0/r32/eax
23671       e9/jump loop/disp32
23672     }
23673 $check-no-breaks:end:
23674     # . restore registers
23675     59/pop-to-ecx
23676     58/pop-to-eax
23677     # . epilogue
23678     89/<- %esp 5/r32/ebp
23679     5d/pop-to-ebp
23680     c3/return
23681 
23682 $check-no-breaks:error:
23683     (write-buffered *(ebp+0x10) "fn ")
23684     8b/-> *(ebp+0xc) 0/r32/eax
23685     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23686     (write-buffered *(ebp+0x10) %eax)
23687     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
23688     (flush *(ebp+0x10))
23689     (stop *(ebp+0x14) 1)
23690     # never gets here
23691 
23692 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23693     # . prologue
23694     55/push-ebp
23695     89/<- %ebp 4/r32/esp
23696     # . save registers
23697     50/push-eax
23698     51/push-ecx
23699     52/push-edx
23700     53/push-ebx
23701     56/push-esi
23702     57/push-edi
23703     # esi = stmt
23704     8b/-> *(ebp+8) 6/r32/esi
23705     # - check for 0 inouts
23706     # var base/ecx: (addr var) = stmt->inouts->value
23707     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23708     3d/compare-eax-and 0/imm32/false
23709     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23710     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23711     89/<- %ecx 0/r32/eax
23712 $check-mu-get-stmt:check-base:
23713     # - check base type
23714     # if it's an 'addr', check that it's in a register
23715     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23716     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23717     89/<- %ebx 0/r32/eax
23718     {
23719       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23720       0f 85/jump-if-!= break/disp32
23721 $check-mu-get-stmt:base-is-compound:
23722       # if (type->left != addr) break
23723       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23724       (simple-mu-type? %eax 2)  # addr => eax
23725       3d/compare-eax-and 0/imm32/false
23726       74/jump-if-= break/disp8
23727 $check-mu-get-stmt:base-is-addr:
23728       # now check for register
23729       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
23730       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
23731 $check-mu-get-stmt:base-is-addr-in-register:
23732       # type->left is now an addr; skip it
23733       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23734       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23735       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
23736 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
23737       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23738       89/<- %ebx 0/r32/eax
23739     }
23740 $check-mu-get-stmt:check-base-typeinfo:
23741     # ensure type is a container
23742     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23743     {
23744       75/jump-if-!= break/disp8
23745       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23746       89/<- %ebx 0/r32/eax
23747     }
23748     # var base-type-id/ebx: type-id = base-type->value
23749     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
23750     (container? %ebx)  # => eax
23751     3d/compare-eax-and 0/imm32/false
23752     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
23753     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
23754     # . var container/ecx: (handle typeinfo)
23755     68/push 0/imm32
23756     68/push 0/imm32
23757     89/<- %ecx 4/r32/esp
23758     # .
23759     (find-typeinfo %ebx %ecx)
23760     (lookup *ecx *(ecx+4))  # => eax
23761     # . reclaim container
23762     81 0/subop/add %esp 8/imm32
23763     # .
23764     89/<- %edx 0/r32/eax
23765     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
23766     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23767     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23768     89/<- %ecx 0/r32/eax
23769     # - check for 1 inout
23770     3d/compare-eax-and 0/imm32/false
23771     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
23772     # var offset/ecx: (addr var) = lookup(offset->value)
23773     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23774     89/<- %ecx 0/r32/eax
23775     # - check for valid field
23776     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
23777     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
23778     # - check for too many inouts
23779     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23780     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23781     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23782     3d/compare-eax-and 0/imm32/false
23783     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
23784     # var output/edi: (addr var) = stmt->outputs->value
23785     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23786     # - check for 0 outputs
23787     3d/compare-eax-and 0/imm32/false
23788     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
23789     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23790     89/<- %edi 0/r32/eax
23791 $check-mu-get-stmt:check-output-type:
23792     # - check output type
23793     # must be in register
23794     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
23795     3d/compare-eax-and 0/imm32
23796     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
23797     # must have a non-atomic type
23798     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23799     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23800     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
23801     # type must start with (addr ...)
23802     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23803     (simple-mu-type? %eax 2)  # => eax
23804     3d/compare-eax-and 0/imm32/false
23805     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
23806 $check-mu-get-stmt:check-output-type-match:
23807     # payload of addr type must match 'type' definition
23808     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23809     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
23810     # if (payload->right == null) payload = payload->left
23811     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
23812     {
23813       75/jump-if-!= break/disp8
23814       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23815     }
23816     89/<- %edi 0/r32/eax
23817     # . var output-name/ecx: (addr array byte)
23818     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23819     89/<- %ecx 0/r32/eax
23820     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
23821     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
23822     (get %eax %ecx 0x10)  # => eax
23823     # .
23824     (lookup *eax *(eax+4))  # => eax
23825     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
23826     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23827     # .
23828     (type-equal? %edi %eax)  # => eax
23829     3d/compare-eax-and 0/imm32/false
23830     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
23831     # - check for too many outputs
23832     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23833     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23834     3d/compare-eax-and 0/imm32/false
23835     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
23836 $check-mu-get-stmt:end:
23837     # . restore registers
23838     5f/pop-to-edi
23839     5e/pop-to-esi
23840     5b/pop-to-ebx
23841     5a/pop-to-edx
23842     59/pop-to-ecx
23843     58/pop-to-eax
23844     # . epilogue
23845     89/<- %esp 5/r32/ebp
23846     5d/pop-to-ebp
23847     c3/return
23848 
23849 $check-mu-get-stmt:error-too-few-inouts:
23850     (write-buffered *(ebp+0x10) "fn ")
23851     8b/-> *(ebp+0xc) 0/r32/eax
23852     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23853     (write-buffered *(ebp+0x10) %eax)
23854     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
23855     (flush *(ebp+0x10))
23856     (stop *(ebp+0x14) 1)
23857     # never gets here
23858 
23859 $check-mu-get-stmt:error-too-many-inouts:
23860     (write-buffered *(ebp+0x10) "fn ")
23861     8b/-> *(ebp+0xc) 0/r32/eax
23862     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23863     (write-buffered *(ebp+0x10) %eax)
23864     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
23865     (flush *(ebp+0x10))
23866     (stop *(ebp+0x14) 1)
23867     # never gets here
23868 
23869 $check-mu-get-stmt:error-too-few-outputs:
23870     (write-buffered *(ebp+0x10) "fn ")
23871     8b/-> *(ebp+0xc) 0/r32/eax
23872     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23873     (write-buffered *(ebp+0x10) %eax)
23874     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
23875     (flush *(ebp+0x10))
23876     (stop *(ebp+0x14) 1)
23877     # never gets here
23878 
23879 $check-mu-get-stmt:error-too-many-outputs:
23880     (write-buffered *(ebp+0x10) "fn ")
23881     8b/-> *(ebp+0xc) 0/r32/eax
23882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23883     (write-buffered *(ebp+0x10) %eax)
23884     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
23885     (flush *(ebp+0x10))
23886     (stop *(ebp+0x14) 1)
23887     # never gets here
23888 
23889 $check-mu-get-stmt:error-bad-base:
23890     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
23891     (write-buffered *(ebp+0x10) "fn ")
23892     8b/-> *(ebp+0xc) 0/r32/eax
23893     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23894     (write-buffered *(ebp+0x10) %eax)
23895     (write-buffered *(ebp+0x10) ": stmt get: var '")
23896     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23897     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23898     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23899     (write-buffered *(ebp+0x10) %eax)
23900     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
23901     (flush *(ebp+0x10))
23902     (stop *(ebp+0x14) 1)
23903     # never gets here
23904 
23905 $check-mu-get-stmt:error-base-type-addr-but-not-register:
23906     (write-buffered *(ebp+0x10) "fn ")
23907     8b/-> *(ebp+0xc) 0/r32/eax
23908     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23909     (write-buffered *(ebp+0x10) %eax)
23910     (write-buffered *(ebp+0x10) ": stmt get: var '")
23911     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23912     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23913     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23914     (write-buffered *(ebp+0x10) %eax)
23915     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
23916     (flush *(ebp+0x10))
23917     (stop *(ebp+0x14) 1)
23918     # never gets here
23919 
23920 $check-mu-get-stmt:error-bad-field:
23921     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
23922     (write-buffered *(ebp+0x10) "fn ")
23923     8b/-> *(ebp+0xc) 0/r32/eax
23924     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23925     (write-buffered *(ebp+0x10) %eax)
23926     (write-buffered *(ebp+0x10) ": stmt get: type '")
23927     # . write(Type-id->data[tmp])
23928     bf/copy-to-edi Type-id/imm32
23929     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23930     {
23931       81 7/subop/compare %esi 0/imm32
23932       74/jump-if-= break/disp8
23933       (write-buffered *(ebp+0x10) %esi)
23934     }
23935     # .
23936     (write-buffered *(ebp+0x10) "' has no member called '")
23937     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23938     (write-buffered *(ebp+0x10) %eax)
23939     (write-buffered *(ebp+0x10) "'\n")
23940     (flush *(ebp+0x10))
23941     (stop *(ebp+0x14) 1)
23942     # never gets here
23943 
23944 $check-mu-get-stmt:error-output-not-in-register:
23945     (write-buffered *(ebp+0x10) "fn ")
23946     8b/-> *(ebp+0xc) 0/r32/eax
23947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23948     (write-buffered *(ebp+0x10) %eax)
23949     (write-buffered *(ebp+0x10) ": stmt get: output '")
23950     (lookup *edi *(edi+4))  # Var-name Var-name => eax
23951     (write-buffered *(ebp+0x10) %eax)
23952     (write-buffered *(ebp+0x10) "' is not in a register\n")
23953     (flush *(ebp+0x10))
23954     (stop *(ebp+0x14) 1)
23955     # never gets here
23956 
23957 $check-mu-get-stmt:error-output-type-not-address:
23958     (write-buffered *(ebp+0x10) "fn ")
23959     8b/-> *(ebp+0xc) 0/r32/eax
23960     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23961     (write-buffered *(ebp+0x10) %eax)
23962     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
23963     (flush *(ebp+0x10))
23964     (stop *(ebp+0x14) 1)
23965     # never gets here
23966 
23967 $check-mu-get-stmt:error-bad-output-type:
23968     (write-buffered *(ebp+0x10) "fn ")
23969     8b/-> *(ebp+0xc) 0/r32/eax
23970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23971     (write-buffered *(ebp+0x10) %eax)
23972     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
23973     (write-buffered *(ebp+0x10) %ecx)
23974     (write-buffered *(ebp+0x10) "' of type '")
23975     bf/copy-to-edi Type-id/imm32
23976     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
23977     {
23978       81 7/subop/compare %esi 0/imm32
23979       74/jump-if-= break/disp8
23980       (write-buffered *(ebp+0x10) %esi)
23981     }
23982     (write-buffered *(ebp+0x10) "'\n")
23983     (flush *(ebp+0x10))
23984     (stop *(ebp+0x14) 1)
23985     # never gets here
23986 
23987 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23988     # . prologue
23989     55/push-ebp
23990     89/<- %ebp 4/r32/esp
23991     # . save registers
23992     50/push-eax
23993     51/push-ecx
23994     52/push-edx
23995     53/push-ebx
23996     56/push-esi
23997     57/push-edi
23998     # esi = stmt
23999     8b/-> *(ebp+8) 6/r32/esi
24000     # - check for 0 inouts
24001     # var base/ecx: (addr var) = stmt->inouts->value
24002     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24003 $check-mu-index-stmt:check-no-inouts:
24004     3d/compare-eax-and 0/imm32
24005     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
24006     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24007     89/<- %ecx 0/r32/eax
24008     # - check base type is either (addr array ...) in register or (array ...) on stack
24009     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24010     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24011     89/<- %ebx 0/r32/eax
24012     # if base-type is an atom, abort with a precise error
24013     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24014     {
24015       74/jump-if-= break/disp8
24016       (simple-mu-type? %ebx 3)  # array => eax
24017       3d/compare-eax-and 0/imm32/false
24018       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
24019       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
24020     }
24021 $check-mu-index-stmt:base-is-compound:
24022     # if type->left not addr or array, abort
24023     {
24024       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24025       (simple-mu-type? %eax 2)  # addr => eax
24026       3d/compare-eax-and 0/imm32/false
24027       75/jump-if-!= break/disp8
24028       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24029       (simple-mu-type? %eax 3)  # array => eax
24030       3d/compare-eax-and 0/imm32/false
24031       75/jump-if-!= break/disp8
24032       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
24033     }
24034     # if (type->left == addr) ensure type->right->left == array and type->register exists
24035     {
24036       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24037       (simple-mu-type? %eax 2)  # addr => eax
24038       3d/compare-eax-and 0/imm32/false
24039       74/jump-if-= break/disp8
24040 $check-mu-index-stmt:base-is-addr:
24041       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24042       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24043       (simple-mu-type? %eax 3)  # array => eax
24044       3d/compare-eax-and 0/imm32/false
24045       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
24046 $check-mu-index-stmt:check-base-addr-is-register:
24047       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24048       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
24049     }
24050     # if (type->left == array) ensure type->register doesn't exist
24051     {
24052       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24053       (simple-mu-type? %eax 3)  # array => eax
24054       3d/compare-eax-and 0/imm32/false
24055       74/jump-if-= break/disp8
24056 $check-mu-index-stmt:base-is-array:
24057       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24058       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
24059     }
24060     # if (base-type->left == addr) base-type = base-type->right
24061     {
24062       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24063       (simple-mu-type? %eax 2)  # addr => eax
24064       3d/compare-eax-and 0/imm32/false
24065       74/jump-if-= break/disp8
24066       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24067       89/<- %ebx 0/r32/eax
24068     }
24069     # - check for 1 inout
24070     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24071     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24072     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24073 $check-mu-index-stmt:check-single-inout:
24074     3d/compare-eax-and 0/imm32
24075     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
24076     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24077     89/<- %ecx 0/r32/eax
24078     # - check index is either a literal or register
24079     # var index-type/edx: (addr type-tree)
24080     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24081     89/<- %edx 0/r32/eax
24082     # if index type is an atom, it must be a literal or int
24083     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24084     {
24085       74/jump-if-= break/disp8
24086 $check-mu-index-stmt:index-type-is-atom:
24087       (simple-mu-type? %edx 0)  # literal => eax
24088       3d/compare-eax-and 0/imm32/false
24089       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24090       (simple-mu-type? %edx 1)  # int => eax
24091       3d/compare-eax-and 0/imm32/false
24092       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
24093       (simple-mu-type? %edx 7)  # offset => eax
24094       3d/compare-eax-and 0/imm32/false
24095       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
24096       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
24097     }
24098     # if index type is a non-atom: it must be an offset
24099     {
24100       75/jump-if-!= break/disp8
24101 $check-mu-index-stmt:index-type-is-non-atom:
24102       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24103       (simple-mu-type? %eax 7)  # offset => eax
24104       3d/compare-eax-and 0/imm32/false
24105       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
24106     }
24107 $check-mu-index-stmt:index-type-done:
24108     # check index is either a literal or in a register
24109     {
24110       (simple-mu-type? %edx 0)  # literal => eax
24111       3d/compare-eax-and 0/imm32/false
24112       75/jump-if-!= break/disp8
24113 $check-mu-index-stmt:check-index-in-register:
24114       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24115       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
24116     }
24117     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
24118     {
24119       (simple-mu-type? %edx 1)  # int => eax
24120       3d/compare-eax-and 0/imm32/false
24121       74/jump-if-= break/disp8
24122 $check-mu-index-stmt:check-index-can-be-int:
24123       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24124       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24125       (array-element-size %eax)  # => eax
24126       3d/compare-eax-and 1/imm32
24127       74/jump-if-= break/disp8
24128       3d/compare-eax-and 2/imm32
24129       74/jump-if-= break/disp8
24130       3d/compare-eax-and 4/imm32
24131       74/jump-if-= break/disp8
24132       3d/compare-eax-and 8/imm32
24133       74/jump-if-= break/disp8
24134       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
24135     }
24136     # - check for too many inouts
24137     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24138     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24139     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24140     3d/compare-eax-and 0/imm32/false
24141     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
24142     # - check for 0 outputs
24143     # var output/edi: (addr var) = stmt->outputs->value
24144     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24145     3d/compare-eax-and 0/imm32/false
24146     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
24147     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24148     89/<- %edi 0/r32/eax
24149     # - check output type
24150     # must have a non-atomic type
24151     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24152     89/<- %edx 0/r32/eax
24153     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24154     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
24155     # type must start with (addr ...)
24156     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24157     (simple-mu-type? %eax 2)  # addr => eax
24158     3d/compare-eax-and 0/imm32/false
24159     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
24160     # if tail(base-type) != tail(output-type) abort
24161     (type-tail %ebx)  # => eax
24162     89/<- %ebx 0/r32/eax
24163     (type-tail %edx)  # => eax
24164     (type-equal? %ebx %eax)  # => eax
24165     3d/compare-eax-and 0/imm32/false
24166     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
24167     # - check for too many outputs
24168     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24169     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24170     3d/compare-eax-and 0/imm32/false
24171     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
24172 $check-mu-index-stmt:end:
24173     # . restore registers
24174     5f/pop-to-edi
24175     5e/pop-to-esi
24176     5b/pop-to-ebx
24177     5a/pop-to-edx
24178     59/pop-to-ecx
24179     58/pop-to-eax
24180     # . epilogue
24181     89/<- %esp 5/r32/ebp
24182     5d/pop-to-ebp
24183     c3/return
24184 
24185 $check-mu-index-stmt:error-base-non-array-type:
24186     (write-buffered *(ebp+0x10) "fn ")
24187     8b/-> *(ebp+0xc) 0/r32/eax
24188     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24189     (write-buffered *(ebp+0x10) %eax)
24190     (write-buffered *(ebp+0x10) ": stmt index: var '")
24191     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24192     (write-buffered *(ebp+0x10) %eax)
24193     (write-buffered *(ebp+0x10) "' is not an array\n")
24194     (flush *(ebp+0x10))
24195     (stop *(ebp+0x14) 1)
24196     # never gets here
24197 
24198 $check-mu-index-stmt:error-base-array-atom-type:
24199     (write-buffered *(ebp+0x10) "fn ")
24200     8b/-> *(ebp+0xc) 0/r32/eax
24201     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24202     (write-buffered *(ebp+0x10) %eax)
24203     (write-buffered *(ebp+0x10) ": stmt index: array '")
24204     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24205     (write-buffered *(ebp+0x10) %eax)
24206     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24207     (flush *(ebp+0x10))
24208     (stop *(ebp+0x14) 1)
24209     # never gets here
24210 
24211 $check-mu-index-stmt:error-base-address-array-type-on-stack:
24212     (write-buffered *(ebp+0x10) "fn ")
24213     8b/-> *(ebp+0xc) 0/r32/eax
24214     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24215     (write-buffered *(ebp+0x10) %eax)
24216     (write-buffered *(ebp+0x10) ": stmt index: var '")
24217     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24218     (write-buffered *(ebp+0x10) %eax)
24219     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24220     (flush *(ebp+0x10))
24221     (stop *(ebp+0x14) 1)
24222     # never gets here
24223 
24224 $check-mu-index-stmt:error-base-array-type-in-register:
24225     (write-buffered *(ebp+0x10) "fn ")
24226     8b/-> *(ebp+0xc) 0/r32/eax
24227     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24228     (write-buffered *(ebp+0x10) %eax)
24229     (write-buffered *(ebp+0x10) ": stmt index: var '")
24230     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24231     (write-buffered *(ebp+0x10) %eax)
24232     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24233     (flush *(ebp+0x10))
24234     (stop *(ebp+0x14) 1)
24235     # never gets here
24236 
24237 $check-mu-index-stmt:error-too-few-inouts:
24238     (write-buffered *(ebp+0x10) "fn ")
24239     8b/-> *(ebp+0xc) 0/r32/eax
24240     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24241     (write-buffered *(ebp+0x10) %eax)
24242     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
24243     (flush *(ebp+0x10))
24244     (stop *(ebp+0x14) 1)
24245     # never gets here
24246 
24247 $check-mu-index-stmt:error-invalid-index-type:
24248     (write-buffered *(ebp+0x10) "fn ")
24249     8b/-> *(ebp+0xc) 0/r32/eax
24250     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24251     (write-buffered *(ebp+0x10) %eax)
24252     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24253     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24254     (write-buffered *(ebp+0x10) %eax)
24255     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24256     (flush *(ebp+0x10))
24257     (stop *(ebp+0x14) 1)
24258     # never gets here
24259 
24260 $check-mu-index-stmt:error-index-offset-atom-type:
24261     (write-buffered *(ebp+0x10) "fn ")
24262     8b/-> *(ebp+0xc) 0/r32/eax
24263     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24264     (write-buffered *(ebp+0x10) %eax)
24265     (write-buffered *(ebp+0x10) ": stmt index: offset '")
24266     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24267     (write-buffered *(ebp+0x10) %eax)
24268     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24269     (flush *(ebp+0x10))
24270     (stop *(ebp+0x14) 1)
24271     # never gets here
24272 
24273 $check-mu-index-stmt:error-index-on-stack:
24274     (write-buffered *(ebp+0x10) "fn ")
24275     8b/-> *(ebp+0xc) 0/r32/eax
24276     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24277     (write-buffered *(ebp+0x10) %eax)
24278     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
24279     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24280     (write-buffered *(ebp+0x10) %eax)
24281     (write-buffered *(ebp+0x10) "' must be in a register\n")
24282     (flush *(ebp+0x10))
24283     (stop *(ebp+0x14) 1)
24284     # never gets here
24285 
24286 $check-mu-index-stmt:error-index-needs-offset:
24287     (write-buffered *(ebp+0x10) "fn ")
24288     8b/-> *(ebp+0xc) 0/r32/eax
24289     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24290     (write-buffered *(ebp+0x10) %eax)
24291     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
24292     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24293     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24294     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24295     (write-buffered *(ebp+0x10) %eax)
24296     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24297     (flush *(ebp+0x10))
24298     (stop *(ebp+0x14) 1)
24299     # never gets here
24300 
24301 $check-mu-index-stmt:error-too-many-inouts:
24302     (write-buffered *(ebp+0x10) "fn ")
24303     8b/-> *(ebp+0xc) 0/r32/eax
24304     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24305     (write-buffered *(ebp+0x10) %eax)
24306     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
24307     (flush *(ebp+0x10))
24308     (stop *(ebp+0x14) 1)
24309     # never gets here
24310 
24311 $check-mu-index-stmt:error-too-few-outputs:
24312     (write-buffered *(ebp+0x10) "fn ")
24313     8b/-> *(ebp+0xc) 0/r32/eax
24314     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24315     (write-buffered *(ebp+0x10) %eax)
24316     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
24317     (flush *(ebp+0x10))
24318     (stop *(ebp+0x14) 1)
24319     # never gets here
24320 
24321 $check-mu-index-stmt:error-too-many-outputs:
24322     (write-buffered *(ebp+0x10) "fn ")
24323     8b/-> *(ebp+0xc) 0/r32/eax
24324     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24325     (write-buffered *(ebp+0x10) %eax)
24326     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
24327     (flush *(ebp+0x10))
24328     (stop *(ebp+0x14) 1)
24329     # never gets here
24330 
24331 $check-mu-index-stmt:error-output-not-in-register:
24332     (write-buffered *(ebp+0x10) "fn ")
24333     8b/-> *(ebp+0xc) 0/r32/eax
24334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24335     (write-buffered *(ebp+0x10) %eax)
24336     (write-buffered *(ebp+0x10) ": stmt index: output '")
24337     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24338     (write-buffered *(ebp+0x10) %eax)
24339     (write-buffered *(ebp+0x10) "' is not in a register\n")
24340     (flush *(ebp+0x10))
24341     (stop *(ebp+0x14) 1)
24342     # never gets here
24343 
24344 $check-mu-index-stmt:error-output-type-not-address:
24345     (write-buffered *(ebp+0x10) "fn ")
24346     8b/-> *(ebp+0xc) 0/r32/eax
24347     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24348     (write-buffered *(ebp+0x10) %eax)
24349     (write-buffered *(ebp+0x10) ": stmt index: output '")
24350     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24351     (write-buffered *(ebp+0x10) %eax)
24352     (write-buffered *(ebp+0x10) "' must be an addr\n")
24353     (flush *(ebp+0x10))
24354     (stop *(ebp+0x14) 1)
24355     # never gets here
24356 
24357 $check-mu-index-stmt:error-bad-output-type:
24358     (write-buffered *(ebp+0x10) "fn ")
24359     8b/-> *(ebp+0xc) 0/r32/eax
24360     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24361     (write-buffered *(ebp+0x10) %eax)
24362     (write-buffered *(ebp+0x10) ": stmt index: output '")
24363     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24364     (write-buffered *(ebp+0x10) %eax)
24365     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24366     (flush *(ebp+0x10))
24367     (stop *(ebp+0x14) 1)
24368     # never gets here
24369 
24370 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24371     # . prologue
24372     55/push-ebp
24373     89/<- %ebp 4/r32/esp
24374     # . save registers
24375     50/push-eax
24376     51/push-ecx
24377     52/push-edx
24378     53/push-ebx
24379     56/push-esi
24380     57/push-edi
24381     # esi = stmt
24382     8b/-> *(ebp+8) 6/r32/esi
24383     # - check for 0 inouts
24384     # var base/ecx: (addr var) = stmt->inouts->value
24385     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24386 $check-mu-length-stmt:check-no-inouts:
24387     3d/compare-eax-and 0/imm32
24388     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
24389     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24390     89/<- %ecx 0/r32/eax
24391     # - check base type is either (addr array ...) in register or (array ...) on stack
24392     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24393     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24394     89/<- %ebx 0/r32/eax
24395     # if base-type is an atom, abort with a precise error
24396     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24397     {
24398       74/jump-if-= break/disp8
24399       (simple-mu-type? %ebx 3)  # array => eax
24400       3d/compare-eax-and 0/imm32/false
24401       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
24402       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24403     }
24404 $check-mu-length-stmt:base-is-compound:
24405     # if type->left not addr or array, abort
24406     {
24407       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24408       (simple-mu-type? %eax 2)  # addr => eax
24409       3d/compare-eax-and 0/imm32/false
24410       75/jump-if-!= break/disp8
24411       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24412       (simple-mu-type? %eax 3)  # array => eax
24413       3d/compare-eax-and 0/imm32/false
24414       75/jump-if-!= break/disp8
24415       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
24416     }
24417     # if (type->left == addr) ensure type->right->left == array and type->register exists
24418     {
24419       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24420       (simple-mu-type? %eax 2)  # addr => eax
24421       3d/compare-eax-and 0/imm32/false
24422       74/jump-if-= break/disp8
24423 $check-mu-length-stmt:base-is-addr:
24424       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24425       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24426       (simple-mu-type? %eax 3)  # array => eax
24427       3d/compare-eax-and 0/imm32/false
24428       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
24429 $check-mu-length-stmt:check-base-addr-is-register:
24430       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24431       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
24432     }
24433     # if (type->left == array) ensure type->register doesn't exist
24434     {
24435       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24436       (simple-mu-type? %eax 3)  # array => eax
24437       3d/compare-eax-and 0/imm32/false
24438       74/jump-if-= break/disp8
24439 $check-mu-length-stmt:base-is-array:
24440       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
24441       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
24442     }
24443     # if (base-type->left == addr) base-type = base-type->right
24444     {
24445       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24446       (simple-mu-type? %eax 2)  # addr => eax
24447       3d/compare-eax-and 0/imm32/false
24448       74/jump-if-= break/disp8
24449       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24450       89/<- %ebx 0/r32/eax
24451     }
24452     # - check for too many inouts
24453     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24454     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24455     3d/compare-eax-and 0/imm32/false
24456     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
24457     # - check for 0 outputs
24458     # var output/edi: (addr var) = stmt->outputs->value
24459     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24460     3d/compare-eax-and 0/imm32/false
24461     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
24462     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24463     89/<- %edi 0/r32/eax
24464     # - check output type
24465     # must have a non-atomic type
24466     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24467     (simple-mu-type? %eax 1)  # int => eax
24468     3d/compare-eax-and 0/imm32/false
24469     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
24470     # - check for too many outputs
24471     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24472     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24473     3d/compare-eax-and 0/imm32/false
24474     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
24475 $check-mu-length-stmt:end:
24476     # . restore registers
24477     5f/pop-to-edi
24478     5e/pop-to-esi
24479     5b/pop-to-ebx
24480     5a/pop-to-edx
24481     59/pop-to-ecx
24482     58/pop-to-eax
24483     # . epilogue
24484     89/<- %esp 5/r32/ebp
24485     5d/pop-to-ebp
24486     c3/return
24487 
24488 $check-mu-length-stmt:error-base-non-array-type:
24489     (write-buffered *(ebp+0x10) "fn ")
24490     8b/-> *(ebp+0xc) 0/r32/eax
24491     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24492     (write-buffered *(ebp+0x10) %eax)
24493     (write-buffered *(ebp+0x10) ": stmt length: var '")
24494     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24495     (write-buffered *(ebp+0x10) %eax)
24496     (write-buffered *(ebp+0x10) "' is not an array\n")
24497     (flush *(ebp+0x10))
24498     (stop *(ebp+0x14) 1)
24499     # never gets here
24500 
24501 $check-mu-length-stmt:error-base-array-atom-type:
24502     (write-buffered *(ebp+0x10) "fn ")
24503     8b/-> *(ebp+0xc) 0/r32/eax
24504     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24505     (write-buffered *(ebp+0x10) %eax)
24506     (write-buffered *(ebp+0x10) ": stmt length: array '")
24507     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24508     (write-buffered *(ebp+0x10) %eax)
24509     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24510     (flush *(ebp+0x10))
24511     (stop *(ebp+0x14) 1)
24512     # never gets here
24513 
24514 $check-mu-length-stmt:error-base-address-array-type-on-stack:
24515     (write-buffered *(ebp+0x10) "fn ")
24516     8b/-> *(ebp+0xc) 0/r32/eax
24517     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24518     (write-buffered *(ebp+0x10) %eax)
24519     (write-buffered *(ebp+0x10) ": stmt length: var '")
24520     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24521     (write-buffered *(ebp+0x10) %eax)
24522     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
24523     (flush *(ebp+0x10))
24524     (stop *(ebp+0x14) 1)
24525     # never gets here
24526 
24527 $check-mu-length-stmt:error-base-array-type-in-register:
24528     (write-buffered *(ebp+0x10) "fn ")
24529     8b/-> *(ebp+0xc) 0/r32/eax
24530     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24531     (write-buffered *(ebp+0x10) %eax)
24532     (write-buffered *(ebp+0x10) ": stmt length: var '")
24533     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24534     (write-buffered *(ebp+0x10) %eax)
24535     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
24536     (flush *(ebp+0x10))
24537     (stop *(ebp+0x14) 1)
24538     # never gets here
24539 
24540 $check-mu-length-stmt:error-too-few-inouts:
24541     (write-buffered *(ebp+0x10) "fn ")
24542     8b/-> *(ebp+0xc) 0/r32/eax
24543     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24544     (write-buffered *(ebp+0x10) %eax)
24545     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
24546     (flush *(ebp+0x10))
24547     (stop *(ebp+0x14) 1)
24548     # never gets here
24549 
24550 $check-mu-length-stmt:error-invalid-index-type:
24551     (write-buffered *(ebp+0x10) "fn ")
24552     8b/-> *(ebp+0xc) 0/r32/eax
24553     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24554     (write-buffered *(ebp+0x10) %eax)
24555     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24556     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24557     (write-buffered *(ebp+0x10) %eax)
24558     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
24559     (flush *(ebp+0x10))
24560     (stop *(ebp+0x14) 1)
24561     # never gets here
24562 
24563 $check-mu-length-stmt:error-index-offset-atom-type:
24564     (write-buffered *(ebp+0x10) "fn ")
24565     8b/-> *(ebp+0xc) 0/r32/eax
24566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24567     (write-buffered *(ebp+0x10) %eax)
24568     (write-buffered *(ebp+0x10) ": stmt length: offset '")
24569     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24570     (write-buffered *(ebp+0x10) %eax)
24571     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24572     (flush *(ebp+0x10))
24573     (stop *(ebp+0x14) 1)
24574     # never gets here
24575 
24576 $check-mu-length-stmt:error-index-on-stack:
24577     (write-buffered *(ebp+0x10) "fn ")
24578     8b/-> *(ebp+0xc) 0/r32/eax
24579     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24580     (write-buffered *(ebp+0x10) %eax)
24581     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
24582     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24583     (write-buffered *(ebp+0x10) %eax)
24584     (write-buffered *(ebp+0x10) "' must be in a register\n")
24585     (flush *(ebp+0x10))
24586     (stop *(ebp+0x14) 1)
24587     # never gets here
24588 
24589 $check-mu-length-stmt:error-index-needs-offset:
24590     (write-buffered *(ebp+0x10) "fn ")
24591     8b/-> *(ebp+0xc) 0/r32/eax
24592     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24593     (write-buffered *(ebp+0x10) %eax)
24594     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
24595     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24596     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24597     (lookup *eax *(eax+4))  # Var-name Var-name => eax
24598     (write-buffered *(ebp+0x10) %eax)
24599     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
24600     (flush *(ebp+0x10))
24601     (stop *(ebp+0x14) 1)
24602     # never gets here
24603 
24604 $check-mu-length-stmt:error-too-many-inouts:
24605     (write-buffered *(ebp+0x10) "fn ")
24606     8b/-> *(ebp+0xc) 0/r32/eax
24607     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24608     (write-buffered *(ebp+0x10) %eax)
24609     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
24610     (flush *(ebp+0x10))
24611     (stop *(ebp+0x14) 1)
24612     # never gets here
24613 
24614 $check-mu-length-stmt:error-too-few-outputs:
24615     (write-buffered *(ebp+0x10) "fn ")
24616     8b/-> *(ebp+0xc) 0/r32/eax
24617     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24618     (write-buffered *(ebp+0x10) %eax)
24619     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
24620     (flush *(ebp+0x10))
24621     (stop *(ebp+0x14) 1)
24622     # never gets here
24623 
24624 $check-mu-length-stmt:error-too-many-outputs:
24625     (write-buffered *(ebp+0x10) "fn ")
24626     8b/-> *(ebp+0xc) 0/r32/eax
24627     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24628     (write-buffered *(ebp+0x10) %eax)
24629     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
24630     (flush *(ebp+0x10))
24631     (stop *(ebp+0x14) 1)
24632     # never gets here
24633 
24634 $check-mu-length-stmt:error-output-not-in-register:
24635     (write-buffered *(ebp+0x10) "fn ")
24636     8b/-> *(ebp+0xc) 0/r32/eax
24637     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24638     (write-buffered *(ebp+0x10) %eax)
24639     (write-buffered *(ebp+0x10) ": stmt length: output '")
24640     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24641     (write-buffered *(ebp+0x10) %eax)
24642     (write-buffered *(ebp+0x10) "' is not in a register\n")
24643     (flush *(ebp+0x10))
24644     (stop *(ebp+0x14) 1)
24645     # never gets here
24646 
24647 $check-mu-length-stmt:error-invalid-output-type:
24648     (write-buffered *(ebp+0x10) "fn ")
24649     8b/-> *(ebp+0xc) 0/r32/eax
24650     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24651     (write-buffered *(ebp+0x10) %eax)
24652     (write-buffered *(ebp+0x10) ": stmt length: output '")
24653     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24654     (write-buffered *(ebp+0x10) %eax)
24655     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24656     (flush *(ebp+0x10))
24657     (stop *(ebp+0x14) 1)
24658     # never gets here
24659 
24660 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24661     # . prologue
24662     55/push-ebp
24663     89/<- %ebp 4/r32/esp
24664     # . save registers
24665     50/push-eax
24666     51/push-ecx
24667     52/push-edx
24668     53/push-ebx
24669     56/push-esi
24670     57/push-edi
24671     # esi = stmt
24672     8b/-> *(ebp+8) 6/r32/esi
24673     # - check for 0 inouts
24674     # var base/ecx: (addr var) = stmt->inouts->value
24675     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24676 $check-mu-compute-offset-stmt:check-no-inouts:
24677     3d/compare-eax-and 0/imm32
24678     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24679     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24680     89/<- %ecx 0/r32/eax
24681     # - check base type is either (addr array ...) in register or (array ...) on stack
24682     # var base-type/ebx: (addr type-tree) = lookup(base->type)
24683     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24684     89/<- %ebx 0/r32/eax
24685     # if base-type is an atom, abort with a precise error
24686     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
24687     {
24688       74/jump-if-= break/disp8
24689       (simple-mu-type? %ebx 3)  # array => eax
24690       3d/compare-eax-and 0/imm32/false
24691       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
24692       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24693     }
24694 $check-mu-compute-offset-stmt:base-is-compound:
24695     # if type->left not addr or array, abort
24696     {
24697       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24698       (simple-mu-type? %eax 2)  # addr => eax
24699       3d/compare-eax-and 0/imm32/false
24700       75/jump-if-!= break/disp8
24701       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24702       (simple-mu-type? %eax 3)  # array => eax
24703       3d/compare-eax-and 0/imm32/false
24704       75/jump-if-!= break/disp8
24705       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24706     }
24707     # if (type->left == addr) ensure type->right->left == array and type->register exists
24708     {
24709       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24710       (simple-mu-type? %eax 2)  # addr => eax
24711       3d/compare-eax-and 0/imm32/false
24712       74/jump-if-= break/disp8
24713 $check-mu-compute-offset-stmt:base-is-addr:
24714       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24715       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24716       (simple-mu-type? %eax 3)  # array => eax
24717       3d/compare-eax-and 0/imm32/false
24718       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
24719     }
24720     # if (base-type->left == addr) base-type = base-type->right
24721     {
24722       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
24723       (simple-mu-type? %eax 2)  # addr => eax
24724       3d/compare-eax-and 0/imm32/false
24725       74/jump-if-= break/disp8
24726       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24727       89/<- %ebx 0/r32/eax
24728     }
24729     # - check for 1 inout
24730     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
24731     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24732     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24733 $check-mu-compute-offset-stmt:check-single-inout:
24734     3d/compare-eax-and 0/imm32
24735     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
24736     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24737     89/<- %ecx 0/r32/eax
24738     # - check index is either a literal or register
24739     # var index-type/edx: (addr type-tree)
24740     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24741     89/<- %edx 0/r32/eax
24742     # index type must be a literal or int
24743     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24744     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24745     {
24746 $check-mu-compute-offset-stmt:index-type-is-atom:
24747       (simple-mu-type? %edx 0)  # literal => eax
24748       3d/compare-eax-and 0/imm32/false
24749       75/jump-if-!= break/disp8
24750       (simple-mu-type? %edx 1)  # int => eax
24751       3d/compare-eax-and 0/imm32/false
24752       75/jump-if-!= break/disp8
24753       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
24754     }
24755     # - check for too many inouts
24756     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24757     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24758     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24759     3d/compare-eax-and 0/imm32/false
24760     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
24761     # - check for 0 outputs
24762     # var output/edi: (addr var) = stmt->outputs->value
24763     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24764     3d/compare-eax-and 0/imm32/false
24765     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
24766     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
24767     89/<- %edi 0/r32/eax
24768     # - check output type
24769     # must have a non-atomic type
24770     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
24771     89/<- %edx 0/r32/eax
24772     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
24773     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24774     # type must start with (offset ...)
24775     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24776     (simple-mu-type? %eax 7)  # offset => eax
24777     3d/compare-eax-and 0/imm32/false
24778     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
24779     # if tail(base-type) != tail(output-type) abort
24780     (type-tail %ebx)  # => eax
24781     89/<- %ebx 0/r32/eax
24782     (type-tail %edx)  # => eax
24783     (type-equal? %ebx %eax)  # => eax
24784     3d/compare-eax-and 0/imm32/false
24785     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
24786     # - check for too many outputs
24787     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24788     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
24789     3d/compare-eax-and 0/imm32/false
24790     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
24791 $check-mu-compute-offset-stmt:end:
24792     # . restore registers
24793     5f/pop-to-edi
24794     5e/pop-to-esi
24795     5b/pop-to-ebx
24796     5a/pop-to-edx
24797     59/pop-to-ecx
24798     58/pop-to-eax
24799     # . epilogue
24800     89/<- %esp 5/r32/ebp
24801     5d/pop-to-ebp
24802     c3/return
24803 
24804 $check-mu-compute-offset-stmt:error-base-non-array-type:
24805     (write-buffered *(ebp+0x10) "fn ")
24806     8b/-> *(ebp+0xc) 0/r32/eax
24807     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24808     (write-buffered *(ebp+0x10) %eax)
24809     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
24810     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24811     (write-buffered *(ebp+0x10) %eax)
24812     (write-buffered *(ebp+0x10) "' is not an array\n")
24813     (flush *(ebp+0x10))
24814     (stop *(ebp+0x14) 1)
24815     # never gets here
24816 
24817 $check-mu-compute-offset-stmt:error-base-array-atom-type:
24818     (write-buffered *(ebp+0x10) "fn ")
24819     8b/-> *(ebp+0xc) 0/r32/eax
24820     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24821     (write-buffered *(ebp+0x10) %eax)
24822     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
24823     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24824     (write-buffered *(ebp+0x10) %eax)
24825     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
24826     (flush *(ebp+0x10))
24827     (stop *(ebp+0x14) 1)
24828     # never gets here
24829 
24830 $check-mu-compute-offset-stmt:error-too-few-inouts:
24831     (write-buffered *(ebp+0x10) "fn ")
24832     8b/-> *(ebp+0xc) 0/r32/eax
24833     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24834     (write-buffered *(ebp+0x10) %eax)
24835     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
24836     (flush *(ebp+0x10))
24837     (stop *(ebp+0x14) 1)
24838     # never gets here
24839 
24840 $check-mu-compute-offset-stmt:error-invalid-index-type:
24841     (write-buffered *(ebp+0x10) "fn ")
24842     8b/-> *(ebp+0xc) 0/r32/eax
24843     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24844     (write-buffered *(ebp+0x10) %eax)
24845     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24846     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24847     (write-buffered *(ebp+0x10) %eax)
24848     (write-buffered *(ebp+0x10) "' must be an int\n")
24849     (flush *(ebp+0x10))
24850     (stop *(ebp+0x14) 1)
24851     # never gets here
24852 
24853 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
24854     (write-buffered *(ebp+0x10) "fn ")
24855     8b/-> *(ebp+0xc) 0/r32/eax
24856     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24857     (write-buffered *(ebp+0x10) %eax)
24858     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
24859     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24860     (write-buffered *(ebp+0x10) %eax)
24861     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
24862     (flush *(ebp+0x10))
24863     (stop *(ebp+0x14) 1)
24864     # never gets here
24865 
24866 $check-mu-compute-offset-stmt:error-index-on-stack:
24867     (write-buffered *(ebp+0x10) "fn ")
24868     8b/-> *(ebp+0xc) 0/r32/eax
24869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24870     (write-buffered *(ebp+0x10) %eax)
24871     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
24872     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
24873     (write-buffered *(ebp+0x10) %eax)
24874     (write-buffered *(ebp+0x10) "' must be in a register\n")
24875     (flush *(ebp+0x10))
24876     (stop *(ebp+0x14) 1)
24877     # never gets here
24878 
24879 $check-mu-compute-offset-stmt:error-too-many-inouts:
24880     (write-buffered *(ebp+0x10) "fn ")
24881     8b/-> *(ebp+0xc) 0/r32/eax
24882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24883     (write-buffered *(ebp+0x10) %eax)
24884     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
24885     (flush *(ebp+0x10))
24886     (stop *(ebp+0x14) 1)
24887     # never gets here
24888 
24889 $check-mu-compute-offset-stmt:error-too-few-outputs:
24890     (write-buffered *(ebp+0x10) "fn ")
24891     8b/-> *(ebp+0xc) 0/r32/eax
24892     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24893     (write-buffered *(ebp+0x10) %eax)
24894     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
24895     (flush *(ebp+0x10))
24896     (stop *(ebp+0x14) 1)
24897     # never gets here
24898 
24899 $check-mu-compute-offset-stmt:error-too-many-outputs:
24900     (write-buffered *(ebp+0x10) "fn ")
24901     8b/-> *(ebp+0xc) 0/r32/eax
24902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24903     (write-buffered *(ebp+0x10) %eax)
24904     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
24905     (flush *(ebp+0x10))
24906     (stop *(ebp+0x14) 1)
24907     # never gets here
24908 
24909 $check-mu-compute-offset-stmt:error-output-not-in-register:
24910     (write-buffered *(ebp+0x10) "fn ")
24911     8b/-> *(ebp+0xc) 0/r32/eax
24912     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24913     (write-buffered *(ebp+0x10) %eax)
24914     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24915     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24916     (write-buffered *(ebp+0x10) %eax)
24917     (write-buffered *(ebp+0x10) "' is not in a register\n")
24918     (flush *(ebp+0x10))
24919     (stop *(ebp+0x14) 1)
24920     # never gets here
24921 
24922 $check-mu-compute-offset-stmt:error-output-type-not-offset:
24923     (write-buffered *(ebp+0x10) "fn ")
24924     8b/-> *(ebp+0xc) 0/r32/eax
24925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24926     (write-buffered *(ebp+0x10) %eax)
24927     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24928     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24929     (write-buffered *(ebp+0x10) %eax)
24930     (write-buffered *(ebp+0x10) "' must be an offset\n")
24931     (flush *(ebp+0x10))
24932     (stop *(ebp+0x14) 1)
24933     # never gets here
24934 
24935 $check-mu-compute-offset-stmt:error-bad-output-type:
24936     (write-buffered *(ebp+0x10) "fn ")
24937     8b/-> *(ebp+0xc) 0/r32/eax
24938     (lookup *eax *(eax+4))  # Function-name Function-name => eax
24939     (write-buffered *(ebp+0x10) %eax)
24940     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
24941     (lookup *edi *(edi+4))  # Var-name Var-name => eax
24942     (write-buffered *(ebp+0x10) %eax)
24943     (write-buffered *(ebp+0x10) "' does not have the right type\n")
24944     (flush *(ebp+0x10))
24945     (stop *(ebp+0x14) 1)
24946     # never gets here
24947 
24948 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24949     # . prologue
24950     55/push-ebp
24951     89/<- %ebp 4/r32/esp
24952     # . save registers
24953     50/push-eax
24954     51/push-ecx
24955     53/push-ebx
24956     56/push-esi
24957     57/push-edi
24958     # esi = stmt
24959     8b/-> *(ebp+8) 6/r32/esi
24960 $check-mu-copy-object-stmt:check-for-output:
24961     # if stmt->outputs abort
24962     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24963     3d/compare-eax-and 0/imm32
24964     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
24965 $check-mu-copy-object-stmt:get-left:
24966     # var dest/edi: (addr stmt-var) = stmt->inouts
24967     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
24968     89/<- %edi 0/r32/eax
24969     # zero inouts
24970     3d/compare-eax-and 0/imm32
24971     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24972 $check-mu-copy-object-stmt:get-src:
24973     # var src/esi: (addr stmt-var) = dest->next
24974     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
24975     89/<- %esi 0/r32/eax
24976     # 1 inout
24977     3d/compare-eax-and 0/imm32
24978     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24979     # > 2 inouts
24980     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
24981     3d/compare-eax-and 0/imm32
24982     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
24983 $check-mu-copy-object-stmt:types:
24984     # var src-type/ecx: (addr type-tree) = src->value->type
24985     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
24986     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24987     89/<- %ecx 0/r32/eax
24988     # if (src->is-deref?) src-type = src-type->payload
24989     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
24990     3d/compare-eax-and 0/imm32/false
24991     {
24992       74/jump-if-= break/disp8
24993       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24994       # if src-type->right is null, src-type = src-type->left
24995       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
24996       {
24997         75/jump-if-!= break/disp8
24998         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24999       }
25000       89/<- %ecx 0/r32/eax
25001     }
25002     # if src-type is not addr, abort
25003     (mu-addr-type? %ecx)  # => eax
25004     3d/compare-eax-and 0/imm32/false
25005     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
25006     # var dest-type/ebx: (addr type-tree) = dest->value->type
25007     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25008     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25009     89/<- %ebx 0/r32/eax
25010     # if (dest->is-deref?) dest-type = dest-type->payload
25011     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25012     3d/compare-eax-and 0/imm32/false
25013     {
25014       74/jump-if-= break/disp8
25015       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25016       # if dest-type->right is null, dest-type = dest-type->left
25017       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25018       {
25019         75/jump-if-!= break/disp8
25020         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25021       }
25022       89/<- %ebx 0/r32/eax
25023     }
25024     # if (dest-type != src-type) abort
25025     (type-equal? %ecx %ebx)  # => eax
25026     3d/compare-eax-and 0/imm32
25027     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
25028 $check-mu-copy-object-stmt:end:
25029     # . restore registers
25030     5f/pop-to-edi
25031     5e/pop-to-esi
25032     5b/pop-to-ebx
25033     59/pop-to-ecx
25034     58/pop-to-eax
25035     # . epilogue
25036     89/<- %esp 5/r32/ebp
25037     5d/pop-to-ebp
25038     c3/return
25039 
25040 $check-mu-copy-object-stmt:error-incorrect-inouts:
25041     (write-buffered *(ebp+0x10) "fn ")
25042     8b/-> *(ebp+0xc) 0/r32/eax
25043     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25044     (write-buffered *(ebp+0x10) %eax)
25045     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
25046     (flush *(ebp+0x10))
25047     (stop *(ebp+0x14) 1)
25048     # never gets here
25049 
25050 $check-mu-copy-object-stmt:error-too-many-outputs:
25051     (write-buffered *(ebp+0x10) "fn ")
25052     8b/-> *(ebp+0xc) 0/r32/eax
25053     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25054     (write-buffered *(ebp+0x10) %eax)
25055     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
25056     (flush *(ebp+0x10))
25057     (stop *(ebp+0x14) 1)
25058     # never gets here
25059 
25060 $check-mu-copy-object-stmt:error-invalid-types:
25061     (write-buffered *(ebp+0x10) "fn ")
25062     8b/-> *(ebp+0xc) 0/r32/eax
25063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25064     (write-buffered *(ebp+0x10) %eax)
25065     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
25066     (flush *(ebp+0x10))
25067     (stop *(ebp+0x14) 1)
25068     # never gets here
25069 
25070 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25071     # . prologue
25072     55/push-ebp
25073     89/<- %ebp 4/r32/esp
25074     # . save registers
25075     50/push-eax
25076     51/push-ecx
25077     53/push-ebx
25078     56/push-esi
25079     57/push-edi
25080     # esi = stmt
25081     8b/-> *(ebp+8) 6/r32/esi
25082 $check-mu-clear-object-stmt:check-for-output:
25083     # if stmt->outputs abort
25084     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25085     3d/compare-eax-and 0/imm32
25086     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
25087 $check-mu-clear-object-stmt:get-left:
25088     # var dest/edi: (addr stmt-var) = stmt->inouts
25089     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25090     89/<- %edi 0/r32/eax
25091     # zero inouts
25092     3d/compare-eax-and 0/imm32
25093     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25094 $check-mu-clear-object-stmt:get-src:
25095     # > 1 inout
25096     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25097     3d/compare-eax-and 0/imm32
25098     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
25099 $check-mu-clear-object-stmt:types:
25100     # var src-type/ecx: (addr type-tree) = src->value->type
25101     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25102     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25103     89/<- %ecx 0/r32/eax
25104     # if (src->is-deref?) src-type = src-type->payload
25105     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25106     3d/compare-eax-and 0/imm32/false
25107     {
25108       74/jump-if-= break/disp8
25109       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25110       # if src-type->right is null, src-type = src-type->left
25111       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25112       {
25113         75/jump-if-!= break/disp8
25114         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25115       }
25116       89/<- %ecx 0/r32/eax
25117     }
25118     # if src-type is not addr, abort
25119     (mu-addr-type? %ecx)  # => eax
25120     3d/compare-eax-and 0/imm32/false
25121     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
25122 $check-mu-clear-object-stmt:end:
25123     # . restore registers
25124     5f/pop-to-edi
25125     5e/pop-to-esi
25126     5b/pop-to-ebx
25127     59/pop-to-ecx
25128     58/pop-to-eax
25129     # . epilogue
25130     89/<- %esp 5/r32/ebp
25131     5d/pop-to-ebp
25132     c3/return
25133 
25134 $check-mu-clear-object-stmt:error-incorrect-inouts:
25135     (write-buffered *(ebp+0x10) "fn ")
25136     8b/-> *(ebp+0xc) 0/r32/eax
25137     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25138     (write-buffered *(ebp+0x10) %eax)
25139     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
25140     (flush *(ebp+0x10))
25141     (stop *(ebp+0x14) 1)
25142     # never gets here
25143 
25144 $check-mu-clear-object-stmt:error-too-many-outputs:
25145     (write-buffered *(ebp+0x10) "fn ")
25146     8b/-> *(ebp+0xc) 0/r32/eax
25147     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25148     (write-buffered *(ebp+0x10) %eax)
25149     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
25150     (flush *(ebp+0x10))
25151     (stop *(ebp+0x14) 1)
25152     # never gets here
25153 
25154 $check-mu-clear-object-stmt:error-invalid-type:
25155     (write-buffered *(ebp+0x10) "fn ")
25156     8b/-> *(ebp+0xc) 0/r32/eax
25157     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25158     (write-buffered *(ebp+0x10) %eax)
25159     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
25160     (flush *(ebp+0x10))
25161     (stop *(ebp+0x14) 1)
25162     # never gets here
25163 
25164 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25165     # . prologue
25166     55/push-ebp
25167     89/<- %ebp 4/r32/esp
25168     # . save registers
25169     50/push-eax
25170     53/push-ebx
25171     56/push-esi
25172     57/push-edi
25173     # esi = stmt
25174     8b/-> *(ebp+8) 6/r32/esi
25175 $check-mu-allocate-stmt:check-for-output:
25176     # if stmt->outputs abort
25177     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25178     3d/compare-eax-and 0/imm32
25179     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
25180 $check-mu-allocate-stmt:get-target:
25181     # var target/edi: (addr stmt-var) = stmt->inouts
25182     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25183     89/<- %edi 0/r32/eax
25184     # zero inouts
25185     3d/compare-eax-and 0/imm32
25186     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25187     # > 1 inouts
25188     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25189     3d/compare-eax-and 0/imm32
25190     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
25191 $check-mu-allocate-stmt:check-type:
25192     # var target-type/ebx: (addr type-tree) = target->value->type
25193     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25194     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25195     89/<- %ebx 0/r32/eax
25196     # if (target->is-deref?) target-type = target-type->payload
25197     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25198     3d/compare-eax-and 0/imm32/false
25199     {
25200       74/jump-if-= break/disp8
25201       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25202       # if target-type->right is null, target-type = target-type->left
25203       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25204       {
25205         75/jump-if-!= break/disp8
25206         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25207       }
25208       89/<- %ebx 0/r32/eax
25209     }
25210     # if target-type is not addr, abort
25211     (mu-addr-type? %ebx)  # => eax
25212     3d/compare-eax-and 0/imm32/false
25213     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25214     # if target-type->right is an atom, abort
25215     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25216     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
25217     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
25218     # if target-type->right->left is not handle, abort
25219     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25220     (simple-mu-type? %eax 4)  # handle => eax
25221     3d/compare-eax-and 0/imm32/false
25222     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
25223 $check-mu-allocate-stmt:end:
25224     # . restore registers
25225     5f/pop-to-edi
25226     5e/pop-to-esi
25227     5b/pop-to-ebx
25228     58/pop-to-eax
25229     # . epilogue
25230     89/<- %esp 5/r32/ebp
25231     5d/pop-to-ebp
25232     c3/return
25233 
25234 $check-mu-allocate-stmt:error-incorrect-inouts:
25235     (write-buffered *(ebp+0x10) "fn ")
25236     8b/-> *(ebp+0xc) 0/r32/eax
25237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25238     (write-buffered *(ebp+0x10) %eax)
25239     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
25240     (flush *(ebp+0x10))
25241     (stop *(ebp+0x14) 1)
25242     # never gets here
25243 
25244 $check-mu-allocate-stmt:error-too-many-outputs:
25245     (write-buffered *(ebp+0x10) "fn ")
25246     8b/-> *(ebp+0xc) 0/r32/eax
25247     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25248     (write-buffered *(ebp+0x10) %eax)
25249     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
25250     (flush *(ebp+0x10))
25251     (stop *(ebp+0x14) 1)
25252     # never gets here
25253 
25254 $check-mu-allocate-stmt:error-invalid-type:
25255     (write-buffered *(ebp+0x10) "fn ")
25256     8b/-> *(ebp+0xc) 0/r32/eax
25257     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25258     (write-buffered *(ebp+0x10) %eax)
25259     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
25260     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25261     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25262     (write-buffered *(ebp+0x10) %eax)
25263     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
25264     (flush *(ebp+0x10))
25265     (stop *(ebp+0x14) 1)
25266     # never gets here
25267 
25268 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25269     # . prologue
25270     55/push-ebp
25271     89/<- %ebp 4/r32/esp
25272     # . save registers
25273     50/push-eax
25274     53/push-ebx
25275     56/push-esi
25276     57/push-edi
25277     # esi = stmt
25278     8b/-> *(ebp+8) 6/r32/esi
25279 $check-mu-populate-stmt:check-for-output:
25280     # if stmt->outputs abort
25281     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25282     3d/compare-eax-and 0/imm32
25283     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
25284 $check-mu-populate-stmt:get-target:
25285     # var target/edi: (addr stmt-var) = stmt->inouts
25286     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25287     89/<- %edi 0/r32/eax
25288     # zero inouts
25289     3d/compare-eax-and 0/imm32
25290     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25291 $check-mu-populate-stmt:get-length:
25292     # var length/esi: (addr stmt-var) = dest->next
25293     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25294     89/<- %esi 0/r32/eax
25295     # 1 inout
25296     3d/compare-eax-and 0/imm32
25297     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25298     # > 2 inouts
25299     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25300     3d/compare-eax-and 0/imm32
25301     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
25302 $check-mu-populate-stmt:check-target-type:
25303     # var target-type/ebx: (addr type-tree) = target->value->type
25304     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25305     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25306     89/<- %ebx 0/r32/eax
25307 $check-mu-populate-stmt:check-target-type-deref:
25308     # if (target->is-deref?) target-type = target-type->payload
25309     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25310     3d/compare-eax-and 0/imm32/false
25311     {
25312       74/jump-if-= break/disp8
25313       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25314       # if target-type->right is null, target-type = target-type->left
25315       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25316       {
25317         75/jump-if-!= break/disp8
25318         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25319       }
25320       89/<- %ebx 0/r32/eax
25321     }
25322 $check-mu-populate-stmt:check-target-type-addr:
25323     # if target-type is not addr, abort
25324     (mu-addr-type? %ebx)  # => eax
25325     3d/compare-eax-and 0/imm32/false
25326     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25327     # if target-type->right is an atom, abort
25328     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25329     89/<- %ebx 0/r32/eax
25330     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25331     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25332 $check-mu-populate-stmt:check-target-type-handle:
25333     # if target-type->right->left is not handle, abort
25334     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25335     (simple-mu-type? %eax 4)  # handle => eax
25336     3d/compare-eax-and 0/imm32/false
25337     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25338     # if target-type->right->right is an atom, abort
25339     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25340     89/<- %ebx 0/r32/eax
25341     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25342     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
25343 $check-mu-populate-stmt:check-target-type-array:
25344     # if target-type->right->right->left is not array, abort
25345     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25346     (simple-mu-type? %eax 3)  # array => eax
25347     3d/compare-eax-and 0/imm32/false
25348     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
25349 $check-mu-populate-stmt:check-length-type:
25350     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25351     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25352     89/<- %ebx 0/r32/eax
25353     (simple-mu-type? %ebx 0)  # literal => eax
25354     3d/compare-eax-and 0/imm32/false
25355     75/jump-if-!= $check-mu-populate-stmt:end/disp8
25356     (simple-mu-type? %ebx 1)  # int => eax
25357     3d/compare-eax-and 0/imm32/false
25358     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
25359 $check-mu-populate-stmt:end:
25360     # . restore registers
25361     5f/pop-to-edi
25362     5e/pop-to-esi
25363     5b/pop-to-ebx
25364     58/pop-to-eax
25365     # . epilogue
25366     89/<- %esp 5/r32/ebp
25367     5d/pop-to-ebp
25368     c3/return
25369 
25370 $check-mu-populate-stmt:error-incorrect-inouts:
25371     (write-buffered *(ebp+0x10) "fn ")
25372     8b/-> *(ebp+0xc) 0/r32/eax
25373     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25374     (write-buffered *(ebp+0x10) %eax)
25375     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
25376     (flush *(ebp+0x10))
25377     (stop *(ebp+0x14) 1)
25378     # never gets here
25379 
25380 $check-mu-populate-stmt:error-too-many-outputs:
25381     (write-buffered *(ebp+0x10) "fn ")
25382     8b/-> *(ebp+0xc) 0/r32/eax
25383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25384     (write-buffered *(ebp+0x10) %eax)
25385     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
25386     (flush *(ebp+0x10))
25387     (stop *(ebp+0x14) 1)
25388     # never gets here
25389 
25390 $check-mu-populate-stmt:error-invalid-target-type:
25391     (write-buffered *(ebp+0x10) "fn ")
25392     8b/-> *(ebp+0xc) 0/r32/eax
25393     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25394     (write-buffered *(ebp+0x10) %eax)
25395     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
25396     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25397     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25398     (write-buffered *(ebp+0x10) %eax)
25399     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
25400     (flush *(ebp+0x10))
25401     (stop *(ebp+0x14) 1)
25402     # never gets here
25403 
25404 $check-mu-populate-stmt:error-invalid-length-type:
25405     (write-buffered *(ebp+0x10) "fn ")
25406     8b/-> *(ebp+0xc) 0/r32/eax
25407     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25408     (write-buffered *(ebp+0x10) %eax)
25409     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
25410     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25411     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25412     (write-buffered *(ebp+0x10) %eax)
25413     (write-buffered *(ebp+0x10) "' must be an int\n")
25414     (flush *(ebp+0x10))
25415     (stop *(ebp+0x14) 1)
25416     # never gets here
25417 
25418 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25419     # . prologue
25420     55/push-ebp
25421     89/<- %ebp 4/r32/esp
25422     # . save registers
25423     50/push-eax
25424     53/push-ebx
25425     56/push-esi
25426     57/push-edi
25427     # esi = stmt
25428     8b/-> *(ebp+8) 6/r32/esi
25429 $check-mu-populate-stream-stmt:check-for-output:
25430     # if stmt->outputs abort
25431     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25432     3d/compare-eax-and 0/imm32
25433     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
25434 $check-mu-populate-stream-stmt:get-target:
25435     # var target/edi: (addr stmt-var) = stmt->inouts
25436     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25437     89/<- %edi 0/r32/eax
25438     # zero inouts
25439     3d/compare-eax-and 0/imm32
25440     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25441 $check-mu-populate-stream-stmt:get-length:
25442     # var length/esi: (addr stmt-var) = dest->next
25443     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25444     89/<- %esi 0/r32/eax
25445     # 1 inout
25446     3d/compare-eax-and 0/imm32
25447     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25448     # > 2 inouts
25449     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25450     3d/compare-eax-and 0/imm32
25451     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
25452 $check-mu-populate-stream-stmt:check-target-type:
25453     # var target-type/ebx: (addr type-tree) = target->value->type
25454     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25455     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25456     89/<- %ebx 0/r32/eax
25457 $check-mu-populate-stream-stmt:check-target-type-deref:
25458     # if (target->is-deref?) target-type = target-type->payload
25459     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
25460     3d/compare-eax-and 0/imm32/false
25461     {
25462       74/jump-if-= break/disp8
25463       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25464       # if target-type->right is null, target-type = target-type->left
25465       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25466       {
25467         75/jump-if-!= break/disp8
25468         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25469       }
25470       89/<- %ebx 0/r32/eax
25471     }
25472 $check-mu-populate-stream-stmt:check-target-type-addr:
25473     # if target-type is not addr, abort
25474     (mu-addr-type? %ebx)  # => eax
25475     3d/compare-eax-and 0/imm32/false
25476     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25477     # if target-type->right is an atom, abort
25478     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25479     89/<- %ebx 0/r32/eax
25480     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25481     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25482 $check-mu-populate-stream-stmt:check-target-type-handle:
25483     # if target-type->right->left is not handle, abort
25484     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25485     (simple-mu-type? %eax 4)  # handle => eax
25486     3d/compare-eax-and 0/imm32/false
25487     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25488     # if target-type->right->right is an atom, abort
25489     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25490     89/<- %ebx 0/r32/eax
25491     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25492     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25493 $check-mu-populate-stream-stmt:check-target-type-stream:
25494     # if target-type->right->right->left is not stream, abort
25495     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25496     (simple-mu-type? %eax 0xb)  # stream => eax
25497     3d/compare-eax-and 0/imm32/false
25498     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
25499 $check-mu-populate-stream-stmt:check-length-type:
25500     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25501     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25502     89/<- %ebx 0/r32/eax
25503     (simple-mu-type? %ebx 0)  # literal => eax
25504     3d/compare-eax-and 0/imm32/false
25505     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
25506     (simple-mu-type? %ebx 1)  # int => eax
25507     3d/compare-eax-and 0/imm32/false
25508     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
25509 $check-mu-populate-stream-stmt:end:
25510     # . restore registers
25511     5f/pop-to-edi
25512     5e/pop-to-esi
25513     5b/pop-to-ebx
25514     58/pop-to-eax
25515     # . epilogue
25516     89/<- %esp 5/r32/ebp
25517     5d/pop-to-ebp
25518     c3/return
25519 
25520 $check-mu-populate-stream-stmt:error-incorrect-inouts:
25521     (write-buffered *(ebp+0x10) "fn ")
25522     8b/-> *(ebp+0xc) 0/r32/eax
25523     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25524     (write-buffered *(ebp+0x10) %eax)
25525     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
25526     (flush *(ebp+0x10))
25527     (stop *(ebp+0x14) 1)
25528     # never gets here
25529 
25530 $check-mu-populate-stream-stmt:error-too-many-outputs:
25531     (write-buffered *(ebp+0x10) "fn ")
25532     8b/-> *(ebp+0xc) 0/r32/eax
25533     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25534     (write-buffered *(ebp+0x10) %eax)
25535     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
25536     (flush *(ebp+0x10))
25537     (stop *(ebp+0x14) 1)
25538     # never gets here
25539 
25540 $check-mu-populate-stream-stmt:error-invalid-target-type:
25541     (write-buffered *(ebp+0x10) "fn ")
25542     8b/-> *(ebp+0xc) 0/r32/eax
25543     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25544     (write-buffered *(ebp+0x10) %eax)
25545     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
25546     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25547     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25548     (write-buffered *(ebp+0x10) %eax)
25549     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
25550     (flush *(ebp+0x10))
25551     (stop *(ebp+0x14) 1)
25552     # never gets here
25553 
25554 $check-mu-populate-stream-stmt:error-invalid-length-type:
25555     (write-buffered *(ebp+0x10) "fn ")
25556     8b/-> *(ebp+0xc) 0/r32/eax
25557     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25558     (write-buffered *(ebp+0x10) %eax)
25559     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
25560     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25561     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25562     (write-buffered *(ebp+0x10) %eax)
25563     (write-buffered *(ebp+0x10) "' must be an int\n")
25564     (flush *(ebp+0x10))
25565     (stop *(ebp+0x14) 1)
25566     # never gets here
25567 
25568 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25569     # . prologue
25570     55/push-ebp
25571     89/<- %ebp 4/r32/esp
25572     # . save registers
25573     50/push-eax
25574     51/push-ecx
25575     52/push-edx
25576     53/push-ebx
25577     56/push-esi
25578     57/push-edi
25579     # esi = stmt
25580     8b/-> *(ebp+8) 6/r32/esi
25581     # - check for 0 inouts
25582     # var base/ecx: (addr var) = stmt->inouts->value
25583     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25584 $check-mu-read-from-stream-stmt:check-no-inouts:
25585     3d/compare-eax-and 0/imm32
25586     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25587     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25588     89/<- %ecx 0/r32/eax
25589     # - check base type is (addr stream T)
25590     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25591     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25592     89/<- %ebx 0/r32/eax
25593 $check-mu-read-from-stream-stmt:check-base-is-compound:
25594     # if base-type is an atom, abort
25595     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25596     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25597 $check-mu-read-from-stream-stmt:check-base-is-addr:
25598     # if type->left not addr, abort
25599     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25600     (simple-mu-type? %eax 2)  # addr => eax
25601     3d/compare-eax-and 0/imm32/false
25602     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25603 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
25604     # base-type = base-type->right
25605     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25606     89/<- %ebx 0/r32/eax
25607     # ensure base-type->left == stream
25608     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25609     (simple-mu-type? %eax 0xb)  # stream => eax
25610     3d/compare-eax-and 0/imm32/false
25611     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
25612     # - check target type is (addr T)
25613     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25614     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25615     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25616 $check-mu-read-from-stream-stmt:check-single-inout:
25617     3d/compare-eax-and 0/imm32
25618     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
25619     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25620     89/<- %ecx 0/r32/eax
25621     # var target-type/edx: (addr type-tree)
25622     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25623     89/<- %edx 0/r32/eax
25624     # if target-type is an atom, it must be a literal or int
25625 $check-mu-read-from-stream-stmt:check-target-is-compound:
25626     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25627     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25628 $check-mu-read-from-stream-stmt:check-target-type:
25629     # target type must start with (addr ...)
25630     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25631     (simple-mu-type? %eax 2)  # addr => eax
25632     3d/compare-eax-and 0/imm32/false
25633     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
25634     # if tail(base-type) != tail(target-type) abort
25635     (type-tail %ebx)  # => eax
25636     89/<- %ebx 0/r32/eax
25637     (type-tail %edx)  # => eax
25638     (type-equal? %ebx %eax)  # => eax
25639     3d/compare-eax-and 0/imm32/false
25640     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
25641 $check-mu-read-from-stream-stmt:check-too-many-inouts:
25642     # - check for too many inouts
25643     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25644     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25645     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25646     3d/compare-eax-and 0/imm32/false
25647     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
25648 $check-mu-read-from-stream-stmt:check-unexpected-output:
25649     # - check for any output
25650     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25651     3d/compare-eax-and 0/imm32/false
25652     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
25653 $check-mu-read-from-stream-stmt:end:
25654     # . restore registers
25655     5f/pop-to-edi
25656     5e/pop-to-esi
25657     5b/pop-to-ebx
25658     5a/pop-to-edx
25659     59/pop-to-ecx
25660     58/pop-to-eax
25661     # . epilogue
25662     89/<- %esp 5/r32/ebp
25663     5d/pop-to-ebp
25664     c3/return
25665 
25666 $check-mu-read-from-stream-stmt:error-invalid-base-type:
25667     (write-buffered *(ebp+0x10) "fn ")
25668     8b/-> *(ebp+0xc) 0/r32/eax
25669     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25670     (write-buffered *(ebp+0x10) %eax)
25671     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
25672     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25673     (write-buffered *(ebp+0x10) %eax)
25674     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25675     (flush *(ebp+0x10))
25676     (stop *(ebp+0x14) 1)
25677     # never gets here
25678 
25679 $check-mu-read-from-stream-stmt:error-too-few-inouts:
25680     (write-buffered *(ebp+0x10) "fn ")
25681     8b/-> *(ebp+0xc) 0/r32/eax
25682     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25683     (write-buffered *(ebp+0x10) %eax)
25684     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
25685     (flush *(ebp+0x10))
25686     (stop *(ebp+0x14) 1)
25687     # never gets here
25688 
25689 $check-mu-read-from-stream-stmt:error-target-type-not-address:
25690     (write-buffered *(ebp+0x10) "fn ")
25691     8b/-> *(ebp+0xc) 0/r32/eax
25692     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25693     (write-buffered *(ebp+0x10) %eax)
25694     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
25695     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25696     (write-buffered *(ebp+0x10) %eax)
25697     (write-buffered *(ebp+0x10) "' must be an addr\n")
25698     (flush *(ebp+0x10))
25699     (stop *(ebp+0x14) 1)
25700     # never gets here
25701 
25702 $check-mu-read-from-stream-stmt:error-invalid-target-type:
25703     (write-buffered *(ebp+0x10) "fn ")
25704     8b/-> *(ebp+0xc) 0/r32/eax
25705     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25706     (write-buffered *(ebp+0x10) %eax)
25707     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
25708     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25709     (write-buffered *(ebp+0x10) %eax)
25710     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25711     (flush *(ebp+0x10))
25712     (stop *(ebp+0x14) 1)
25713     # never gets here
25714 
25715 $check-mu-read-from-stream-stmt:error-too-many-inouts:
25716     (write-buffered *(ebp+0x10) "fn ")
25717     8b/-> *(ebp+0xc) 0/r32/eax
25718     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25719     (write-buffered *(ebp+0x10) %eax)
25720     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
25721     (flush *(ebp+0x10))
25722     (stop *(ebp+0x14) 1)
25723     # never gets here
25724 
25725 $check-mu-read-from-stream-stmt:error-unexpected-output:
25726     (write-buffered *(ebp+0x10) "fn ")
25727     8b/-> *(ebp+0xc) 0/r32/eax
25728     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25729     (write-buffered *(ebp+0x10) %eax)
25730     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
25731     (flush *(ebp+0x10))
25732     (stop *(ebp+0x14) 1)
25733     # never gets here
25734 
25735 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25736     # . prologue
25737     55/push-ebp
25738     89/<- %ebp 4/r32/esp
25739     # . save registers
25740     50/push-eax
25741     51/push-ecx
25742     52/push-edx
25743     53/push-ebx
25744     56/push-esi
25745     57/push-edi
25746     # esi = stmt
25747     8b/-> *(ebp+8) 6/r32/esi
25748     # - check for 0 inouts
25749     # var base/ecx: (addr var) = stmt->inouts->value
25750     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25751 $check-mu-write-to-stream-stmt:check-no-inouts:
25752     3d/compare-eax-and 0/imm32
25753     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25754     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25755     89/<- %ecx 0/r32/eax
25756     # - check base type is (addr stream T)
25757     # var base-type/ebx: (addr type-tree) = lookup(base->type)
25758     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25759     89/<- %ebx 0/r32/eax
25760 $check-mu-write-to-stream-stmt:check-base-is-compound:
25761     # if base-type is an atom, abort
25762     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
25763     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25764 $check-mu-write-to-stream-stmt:check-base-is-addr:
25765     # if type->left not addr, abort
25766     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
25767     (simple-mu-type? %eax 2)  # addr => eax
25768     3d/compare-eax-and 0/imm32/false
25769     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25770 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
25771     # base-type = base-type->right
25772     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
25773     89/<- %ebx 0/r32/eax
25774     # ensure base-type->left == stream
25775     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25776     (simple-mu-type? %eax 0xb)  # stream => eax
25777     3d/compare-eax-and 0/imm32/false
25778     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
25779     # - check target type is (addr T)
25780     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
25781     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25782     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25783 $check-mu-write-to-stream-stmt:check-single-inout:
25784     3d/compare-eax-and 0/imm32
25785     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
25786     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25787     89/<- %ecx 0/r32/eax
25788     # var target-type/edx: (addr type-tree)
25789     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25790     89/<- %edx 0/r32/eax
25791     # if target-type is an atom, it must be a literal or int
25792 $check-mu-write-to-stream-stmt:check-target-is-compound:
25793     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
25794     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25795 $check-mu-write-to-stream-stmt:check-target-type:
25796     # target type must start with (addr ...)
25797     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
25798     (simple-mu-type? %eax 2)  # addr => eax
25799     3d/compare-eax-and 0/imm32/false
25800     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
25801     # if tail(base-type) != tail(target-type) abort
25802     (type-tail %ebx)  # => eax
25803     89/<- %ebx 0/r32/eax
25804     (type-tail %edx)  # => eax
25805     (type-equal? %ebx %eax)  # => eax
25806     3d/compare-eax-and 0/imm32/false
25807     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
25808 $check-mu-write-to-stream-stmt:check-too-many-inouts:
25809     # - check for too many inouts
25810     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25811     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25812     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
25813     3d/compare-eax-and 0/imm32/false
25814     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
25815 $check-mu-write-to-stream-stmt:check-unexpected-output:
25816     # - check for any output
25817     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25818     3d/compare-eax-and 0/imm32/false
25819     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
25820 $check-mu-write-to-stream-stmt:end:
25821     # . restore registers
25822     5f/pop-to-edi
25823     5e/pop-to-esi
25824     5b/pop-to-ebx
25825     5a/pop-to-edx
25826     59/pop-to-ecx
25827     58/pop-to-eax
25828     # . epilogue
25829     89/<- %esp 5/r32/ebp
25830     5d/pop-to-ebp
25831     c3/return
25832 
25833 $check-mu-write-to-stream-stmt:error-invalid-base-type:
25834     (write-buffered *(ebp+0x10) "fn ")
25835     8b/-> *(ebp+0xc) 0/r32/eax
25836     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25837     (write-buffered *(ebp+0x10) %eax)
25838     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
25839     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25840     (write-buffered *(ebp+0x10) %eax)
25841     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
25842     (flush *(ebp+0x10))
25843     (stop *(ebp+0x14) 1)
25844     # never gets here
25845 
25846 $check-mu-write-to-stream-stmt:error-too-few-inouts:
25847     (write-buffered *(ebp+0x10) "fn ")
25848     8b/-> *(ebp+0xc) 0/r32/eax
25849     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25850     (write-buffered *(ebp+0x10) %eax)
25851     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
25852     (flush *(ebp+0x10))
25853     (stop *(ebp+0x14) 1)
25854     # never gets here
25855 
25856 $check-mu-write-to-stream-stmt:error-target-type-not-address:
25857     (write-buffered *(ebp+0x10) "fn ")
25858     8b/-> *(ebp+0xc) 0/r32/eax
25859     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25860     (write-buffered *(ebp+0x10) %eax)
25861     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
25862     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25863     (write-buffered *(ebp+0x10) %eax)
25864     (write-buffered *(ebp+0x10) "' must be an addr\n")
25865     (flush *(ebp+0x10))
25866     (stop *(ebp+0x14) 1)
25867     # never gets here
25868 
25869 $check-mu-write-to-stream-stmt:error-invalid-target-type:
25870     (write-buffered *(ebp+0x10) "fn ")
25871     8b/-> *(ebp+0xc) 0/r32/eax
25872     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25873     (write-buffered *(ebp+0x10) %eax)
25874     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
25875     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25876     (write-buffered *(ebp+0x10) %eax)
25877     (write-buffered *(ebp+0x10) "' does not have the right type\n")
25878     (flush *(ebp+0x10))
25879     (stop *(ebp+0x14) 1)
25880     # never gets here
25881 
25882 $check-mu-write-to-stream-stmt:error-too-many-inouts:
25883     (write-buffered *(ebp+0x10) "fn ")
25884     8b/-> *(ebp+0xc) 0/r32/eax
25885     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25886     (write-buffered *(ebp+0x10) %eax)
25887     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
25888     (flush *(ebp+0x10))
25889     (stop *(ebp+0x14) 1)
25890     # never gets here
25891 
25892 $check-mu-write-to-stream-stmt:error-unexpected-output:
25893     (write-buffered *(ebp+0x10) "fn ")
25894     8b/-> *(ebp+0xc) 0/r32/eax
25895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
25896     (write-buffered *(ebp+0x10) %eax)
25897     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
25898     (flush *(ebp+0x10))
25899     (stop *(ebp+0x14) 1)
25900     # never gets here
25901 
25902 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25903     # . prologue
25904     55/push-ebp
25905     89/<- %ebp 4/r32/esp
25906     # . save registers
25907     50/push-eax
25908     51/push-ecx
25909     52/push-edx
25910     56/push-esi
25911     57/push-edi
25912 $check-mu-convert-stmt:get-output:
25913     # esi = stmt
25914     8b/-> *(ebp+8) 6/r32/esi
25915     # var output/edi: (addr stmt-var) = stmt->outputs
25916     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
25917     89/<- %edi 0/r32/eax
25918     # zero outputs
25919     3d/compare-eax-and 0/imm32
25920     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
25921     # > 1 output
25922     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
25923     3d/compare-eax-and 0/imm32
25924     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
25925 $check-mu-convert-stmt:get-inout:
25926     # var inout/esi: (addr stmt-var) = stmt->inouts
25927     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25928     89/<- %esi 0/r32/eax
25929     # zero inouts
25930     3d/compare-eax-and 0/imm32
25931     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
25932     # > 1 inout
25933     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25934     3d/compare-eax-and 0/imm32
25935     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
25936 $check-mu-convert-stmt:types:
25937     # var inout-type/ecx: (addr type-tree) = inout->value->type
25938     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25939     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25940     89/<- %ecx 0/r32/eax
25941     # if (inout->is-deref?) inout-type = inout-type->payload
25942     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
25943     3d/compare-eax-and 0/imm32/false
25944     {
25945       74/jump-if-= break/disp8
25946       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
25947       # if inout-type->right is null, t = inout-type->left
25948       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
25949       {
25950         75/jump-if-!= break/disp8
25951         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
25952       }
25953       89/<- %ecx 0/r32/eax
25954     }
25955     # if input is not int or float, abort
25956     {
25957       (simple-mu-type? %ecx 1)  # int => eax
25958       3d/compare-eax-and 0/imm32/false
25959       75/jump-if-!= break/disp8
25960       (simple-mu-type? %ecx 0xf)  # float => eax
25961       3d/compare-eax-and 0/imm32/false
25962       75/jump-if-!= break/disp8
25963       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
25964     }
25965     # if output not in register, abort
25966     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25967     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25968     3d/compare-eax-and 0/imm32
25969     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
25970     # var output-type/edx: (addr type-tree) = output->value->type
25971     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
25972     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
25973     89/<- %edx 0/r32/eax
25974     # if output is not int or float, abort
25975     {
25976       (simple-mu-type? %edx 1)  # int => eax
25977       3d/compare-eax-and 0/imm32/false
25978       75/jump-if-!= break/disp8
25979       (simple-mu-type? %edx 0xf)  # float => eax
25980       3d/compare-eax-and 0/imm32/false
25981       75/jump-if-!= break/disp8
25982       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
25983     }
25984     # if both are ints, abort
25985     {
25986       (simple-mu-type? %edx 1)  # int => eax
25987       3d/compare-eax-and 0/imm32/false
25988       74/jump-if-= break/disp8
25989       (simple-mu-type? %ecx 1)  # int => eax
25990       3d/compare-eax-and 0/imm32/false
25991       74/jump-if-= break/disp8
25992       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
25993     }
25994     # if both are floats, abort
25995     {
25996       (simple-mu-type? %edx 0xf)  # float => eax
25997       3d/compare-eax-and 0/imm32/false
25998       74/jump-if-= break/disp8
25999       (simple-mu-type? %ecx 0xf)  # float => eax
26000       3d/compare-eax-and 0/imm32/false
26001       74/jump-if-= break/disp8
26002       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
26003     }
26004 $check-mu-convert-stmt:end:
26005     # . restore registers
26006     5f/pop-to-edi
26007     5e/pop-to-esi
26008     5a/pop-to-edx
26009     59/pop-to-ecx
26010     58/pop-to-eax
26011     # . epilogue
26012     89/<- %esp 5/r32/ebp
26013     5d/pop-to-ebp
26014     c3/return
26015 
26016 $check-mu-convert-stmt:error-no-inout:
26017     (write-buffered *(ebp+0x10) "fn ")
26018     8b/-> *(ebp+0xc) 0/r32/eax
26019     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26020     (write-buffered *(ebp+0x10) %eax)
26021     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
26022     (flush *(ebp+0x10))
26023     (stop *(ebp+0x14) 1)
26024     # never gets here
26025 
26026 $check-mu-convert-stmt:error-too-many-inouts:
26027     (write-buffered *(ebp+0x10) "fn ")
26028     8b/-> *(ebp+0xc) 0/r32/eax
26029     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26030     (write-buffered *(ebp+0x10) %eax)
26031     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
26032     (flush *(ebp+0x10))
26033     (stop *(ebp+0x14) 1)
26034     # never gets here
26035 
26036 $check-mu-convert-stmt:error-no-output:
26037     (write-buffered *(ebp+0x10) "fn ")
26038     8b/-> *(ebp+0xc) 0/r32/eax
26039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26040     (write-buffered *(ebp+0x10) %eax)
26041     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
26042     (flush *(ebp+0x10))
26043     (stop *(ebp+0x14) 1)
26044     # never gets here
26045 
26046 $check-mu-convert-stmt:error-output-not-in-register:
26047     (write-buffered *(ebp+0x10) "fn ")
26048     8b/-> *(ebp+0xc) 0/r32/eax
26049     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26050     (write-buffered *(ebp+0x10) %eax)
26051     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26052     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26053     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26054     (write-buffered *(ebp+0x10) %eax)
26055     (write-buffered *(ebp+0x10) "' not in a register\n")
26056     (flush *(ebp+0x10))
26057     (stop *(ebp+0x14) 1)
26058     # never gets here
26059 
26060 $check-mu-convert-stmt:error-too-many-outputs:
26061     (write-buffered *(ebp+0x10) "fn ")
26062     8b/-> *(ebp+0xc) 0/r32/eax
26063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26064     (write-buffered *(ebp+0x10) %eax)
26065     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
26066     (flush *(ebp+0x10))
26067     (stop *(ebp+0x14) 1)
26068     # never gets here
26069 
26070 $check-mu-convert-stmt:error-invalid-inout-type:
26071     (write-buffered *(ebp+0x10) "fn ")
26072     8b/-> *(ebp+0xc) 0/r32/eax
26073     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26074     (write-buffered *(ebp+0x10) %eax)
26075     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
26076     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
26077     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26078     (write-buffered *(ebp+0x10) %eax)
26079     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26080     (flush *(ebp+0x10))
26081     (stop *(ebp+0x14) 1)
26082     # never gets here
26083 
26084 $check-mu-convert-stmt:error-invalid-output-type:
26085     (write-buffered *(ebp+0x10) "fn ")
26086     8b/-> *(ebp+0xc) 0/r32/eax
26087     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26088     (write-buffered *(ebp+0x10) %eax)
26089     (write-buffered *(ebp+0x10) ": stmt convert: output '")
26090     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
26091     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26092     (write-buffered *(ebp+0x10) %eax)
26093     (write-buffered *(ebp+0x10) "' must be an int or float\n")
26094     (flush *(ebp+0x10))
26095     (stop *(ebp+0x14) 1)
26096     # never gets here
26097 
26098 $check-mu-convert-stmt:error-int-to-int:
26099     (write-buffered *(ebp+0x10) "fn ")
26100     8b/-> *(ebp+0xc) 0/r32/eax
26101     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26102     (write-buffered *(ebp+0x10) %eax)
26103     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
26104     (flush *(ebp+0x10))
26105     (stop *(ebp+0x14) 1)
26106     # never gets here
26107 
26108 $check-mu-convert-stmt:error-float-to-float:
26109     (write-buffered *(ebp+0x10) "fn ")
26110     8b/-> *(ebp+0xc) 0/r32/eax
26111     (lookup *eax *(eax+4))  # Function-name Function-name => eax
26112     (write-buffered *(ebp+0x10) %eax)
26113     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
26114     (flush *(ebp+0x10))
26115     (stop *(ebp+0x14) 1)
26116     # never gets here
26117 
26118 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26119     # . prologue
26120     55/push-ebp
26121     89/<- %ebp 4/r32/esp
26122     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
26123     68/push 0/imm32
26124     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
26125     81 5/subop/subtract %esp 0x60/imm32
26126     68/push 0x60/imm32/size
26127     68/push 0/imm32/read
26128     68/push 0/imm32/write
26129     # save a pointer to type-parameters-storage at type-parameters
26130     89/<- *(ebp-4) 4/r32/esp
26131     (clear-stream *(ebp-4))
26132     # . save registers
26133     50/push-eax
26134     51/push-ecx
26135     52/push-edx
26136     53/push-ebx
26137     56/push-esi
26138     57/push-edi
26139     # esi = stmt
26140     8b/-> *(ebp+8) 6/r32/esi
26141     # edi = callee
26142     8b/-> *(ebp+0xc) 7/r32/edi
26143     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
26144     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26145     89/<- %ecx 0/r32/eax
26146     # var expected/edx: (addr list var) = lookup(f->inouts)
26147     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
26148     89/<- %edx 0/r32/eax
26149     {
26150 $check-mu-call:check-for-inouts:
26151       # if (inouts == 0) break
26152       81 7/subop/compare %ecx 0/imm32
26153       0f 84/jump-if-= break/disp32
26154       # if (expected == 0) error
26155       81 7/subop/compare %edx 0/imm32
26156       0f 84/jump-if-= break/disp32
26157 $check-mu-call:check-null-addr:
26158       # if (inouts->value->name == "0") continue
26159       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26160       (lookup *eax *(eax+4))  # Var-name Var-name => eax
26161       (string-equal? %eax "0")  # => eax
26162       3d/compare-eax-and 0/imm32/false
26163       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
26164 $check-mu-call:check-inout-type:
26165       # var t/ebx: (addr type-tree) = inouts->value->type
26166       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26167       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26168       89/<- %ebx 0/r32/eax
26169       # if (inouts->is-deref?) t = t->right
26170       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26171       {
26172         74/jump-if-= break/disp8
26173         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26174         89/<- %ebx 0/r32/eax
26175         # if t->right is null, t = t->left
26176         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
26177         75/jump-if-!= break/disp8
26178         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
26179         89/<- %ebx 0/r32/eax
26180       }
26181       # var v2/eax: (addr v) = lookup(expected->value)
26182       (lookup *edx *(edx+4))  # List-value List-value => eax
26183       # var t2/eax: (addr type-tree) = lookup(v2->type)
26184       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26185       # if (t != t2) error
26186       (type-match? %eax %ebx *(ebp-4))  # => eax
26187       3d/compare-eax-and 0/imm32/false
26188       {
26189         0f 85/jump-if-!= break/disp32
26190         (write-buffered *(ebp+0x14) "fn ")
26191         8b/-> *(ebp+0x10) 0/r32/eax
26192         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26193         (write-buffered *(ebp+0x14) %eax)
26194         (write-buffered *(ebp+0x14) ": call ")
26195         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26196         (write-buffered *(ebp+0x14) %eax)
26197         (write-buffered *(ebp+0x14) ": type for inout '")
26198         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26199         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26200         (write-buffered *(ebp+0x14) %eax)
26201         (write-buffered *(ebp+0x14) "' is not right\n")
26202         (flush *(ebp+0x14))
26203         (stop *(ebp+0x18) 1)
26204       }
26205 $check-mu-call:continue-to-next-inout:
26206       # inouts = lookup(inouts->next)
26207       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26208       89/<- %ecx 0/r32/eax
26209       # expected = lookup(expected->next)
26210       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26211       89/<- %edx 0/r32/eax
26212       #
26213       e9/jump loop/disp32
26214     }
26215 $check-mu-call:check-inout-count:
26216     # if (inouts == expected) proceed
26217     39/compare %ecx 2/r32/edx
26218     {
26219       0f 84/jump-if-= break/disp32
26220       # exactly one of the two is null
26221       # if (inouts == 0) error("too many inouts")
26222       {
26223         81 7/subop/compare %ecx 0/imm32
26224         0f 84/jump-if-= break/disp32
26225         (write-buffered *(ebp+0x14) "fn ")
26226         8b/-> *(ebp+0x10) 0/r32/eax
26227         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26228         (write-buffered *(ebp+0x14) %eax)
26229         (write-buffered *(ebp+0x14) ": call ")
26230         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26231         (write-buffered *(ebp+0x14) %eax)
26232         (write-buffered *(ebp+0x14) ": too many inouts\n")
26233         (flush *(ebp+0x14))
26234         (stop *(ebp+0x18) 1)
26235       }
26236       # if (expected == 0) error("too few inouts")
26237       {
26238         81 7/subop/compare %edx 0/imm32
26239         0f 84/jump-if-= break/disp32
26240         (write-buffered *(ebp+0x14) "fn ")
26241         8b/-> *(ebp+0x10) 0/r32/eax
26242         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26243         (write-buffered *(ebp+0x14) %eax)
26244         (write-buffered *(ebp+0x14) ": call ")
26245         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26246         (write-buffered *(ebp+0x14) %eax)
26247         (write-buffered *(ebp+0x14) ": too few inouts\n")
26248         (flush *(ebp+0x14))
26249         (stop *(ebp+0x18) 1)
26250       }
26251     }
26252 $check-mu-call:check-outputs:
26253     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
26254     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26255     89/<- %ecx 0/r32/eax
26256     # var expected/edx: (addr list var) = lookup(f->outputs)
26257     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
26258     89/<- %edx 0/r32/eax
26259     {
26260 $check-mu-call:check-for-outputs:
26261       # if (outputs == 0) break
26262       81 7/subop/compare %ecx 0/imm32
26263       0f 84/jump-if-= break/disp32
26264       # if (expected == 0) error
26265       81 7/subop/compare %edx 0/imm32
26266       0f 84/jump-if-= break/disp32
26267 $check-mu-call:check-output-type:
26268       # var v/eax: (addr v) = lookup(outputs->value)
26269       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26270       # var t/ebx: (addr type-tree) = lookup(v->type)
26271       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26272       89/<- %ebx 0/r32/eax
26273       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
26274       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26275       {
26276         74/jump-if-= break/disp8
26277         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
26278         89/<- %ebx 0/r32/eax
26279       }
26280       # var v2/eax: (addr v) = lookup(expected->value)
26281       (lookup *edx *(edx+4))  # List-value List-value => eax
26282       # var t2/eax: (addr type-tree) = lookup(v2->type)
26283       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26284       # if (t != t2) error
26285       (type-match? %eax %ebx *(ebp-4))  # => eax
26286       3d/compare-eax-and 0/imm32/false
26287       {
26288         0f 85/jump-if-!= break/disp32
26289         (write-buffered *(ebp+0x14) "fn ")
26290         8b/-> *(ebp+0x10) 0/r32/eax
26291         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26292         (write-buffered *(ebp+0x14) %eax)
26293         (write-buffered *(ebp+0x14) ": call ")
26294         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26295         (write-buffered *(ebp+0x14) %eax)
26296         (write-buffered *(ebp+0x14) ": type for output '")
26297         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26298         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26299         (write-buffered *(ebp+0x14) %eax)
26300         (write-buffered *(ebp+0x14) "' is not right\n")
26301         (flush *(ebp+0x14))
26302         (stop *(ebp+0x18) 1)
26303       }
26304 $check-mu-call:check-output-register:
26305       # var v/eax: (addr v) = lookup(outputs->value)
26306       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26307       # var r/ebx: (addr array byte) = lookup(v->register)
26308       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26309       89/<- %ebx 0/r32/eax
26310       # if (r == 0) error
26311       3d/compare-eax-and 0/imm32
26312       {
26313         0f 85/jump-if-!= break/disp32
26314         (write-buffered *(ebp+0x14) "fn ")
26315         8b/-> *(ebp+0x10) 0/r32/eax
26316         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26317         (write-buffered *(ebp+0x14) %eax)
26318         (write-buffered *(ebp+0x14) ": call ")
26319         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26320         (write-buffered *(ebp+0x14) %eax)
26321         (write-buffered *(ebp+0x14) ": output '")
26322         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26323         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26324         (write-buffered *(ebp+0x14) %eax)
26325         (write-buffered *(ebp+0x14) "' is not in a register\n")
26326         (flush *(ebp+0x14))
26327         (stop *(ebp+0x18) 1)
26328       }
26329       # var v2/eax: (addr v) = lookup(expected->value)
26330       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
26331       # var r2/eax: (addr array byte) = lookup(v2->register)
26332       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
26333       # if (r != r2) error
26334       (string-equal? %eax %ebx)  # => eax
26335       3d/compare-eax-and 0/imm32/false
26336       {
26337         0f 85/jump-if-!= break/disp32
26338         (write-buffered *(ebp+0x14) "fn ")
26339         8b/-> *(ebp+0x10) 0/r32/eax
26340         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26341         (write-buffered *(ebp+0x14) %eax)
26342         (write-buffered *(ebp+0x14) ": call ")
26343         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26344         (write-buffered *(ebp+0x14) %eax)
26345         (write-buffered *(ebp+0x14) ": register for output '")
26346         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26347         (lookup *eax *(eax+4))  # Var-name Var-name => eax
26348         (write-buffered *(ebp+0x14) %eax)
26349         (write-buffered *(ebp+0x14) "' is not right\n")
26350         (flush *(ebp+0x14))
26351         (stop *(ebp+0x18) 1)
26352       }
26353 $check-mu-call:continue-to-next-output:
26354       # outputs = lookup(outputs->next)
26355       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26356       89/<- %ecx 0/r32/eax
26357       # expected = lookup(expected->next)
26358       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
26359       89/<- %edx 0/r32/eax
26360       #
26361       e9/jump loop/disp32
26362     }
26363 $check-mu-call:check-output-count:
26364     # if (outputs == expected) proceed
26365     39/compare %ecx 2/r32/edx
26366     {
26367       0f 84/jump-if-= break/disp32
26368       # exactly one of the two is null
26369       # if (outputs == 0) error("too many outputs")
26370       {
26371         81 7/subop/compare %ecx 0/imm32
26372         0f 84/jump-if-= break/disp32
26373         (write-buffered *(ebp+0x14) "fn ")
26374         8b/-> *(ebp+0x10) 0/r32/eax
26375         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26376         (write-buffered *(ebp+0x14) %eax)
26377         (write-buffered *(ebp+0x14) ": call ")
26378         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26379         (write-buffered *(ebp+0x14) %eax)
26380         (write-buffered *(ebp+0x14) ": too many outputs\n")
26381         (flush *(ebp+0x14))
26382         (stop *(ebp+0x18) 1)
26383       }
26384       # if (expected == 0) error("too few outputs")
26385       {
26386         81 7/subop/compare %edx 0/imm32
26387         0f 84/jump-if-= break/disp32
26388         (write-buffered *(ebp+0x14) "fn ")
26389         8b/-> *(ebp+0x10) 0/r32/eax
26390         (lookup *eax *(eax+4))  # Function-name Function-name => eax
26391         (write-buffered *(ebp+0x14) %eax)
26392         (write-buffered *(ebp+0x14) ": call ")
26393         (lookup *edi *(edi+4))  # Function-name Function-name => eax
26394         (write-buffered *(ebp+0x14) %eax)
26395         (write-buffered *(ebp+0x14) ": too few outputs\n")
26396         (flush *(ebp+0x14))
26397         (stop *(ebp+0x18) 1)
26398       }
26399     }
26400 $check-mu-call:end:
26401     # . restore registers
26402     5f/pop-to-edi
26403     5e/pop-to-esi
26404     5b/pop-to-ebx
26405     5a/pop-to-edx
26406     59/pop-to-ecx
26407     58/pop-to-eax
26408     # . reclaim locals exclusively on the stack
26409     81 0/subop/add %esp 0x70/imm32
26410     # . epilogue
26411     89/<- %esp 5/r32/ebp
26412     5d/pop-to-ebp
26413     c3/return
26414 
26415 # like type-equal? but takes literals type parameters into account
26416 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26417     # . prologue
26418     55/push-ebp
26419     89/<- %ebp 4/r32/esp
26420     # if (call is literal and def is numberlike) return true
26421     {
26422 $type-match?:check-literal-int:
26423       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
26424       3d/compare-eax-and 0/imm32/false
26425       74/jump-if-= break/disp8
26426       (mu-numberlike-output? *(ebp+8))  # => eax
26427       3d/compare-eax-and 0/imm32/false
26428       74/jump-if-= break/disp8
26429       b8/copy-to-eax 1/imm32/true
26430       e9/jump $type-match?:end/disp32
26431     }
26432     # if (call is literal-string and def is string) return true
26433     {
26434 $type-match?:check-literal-string:
26435       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
26436       3d/compare-eax-and 0/imm32/false
26437       74/jump-if-= break/disp8
26438       (mu-string-type? *(ebp+8))  # => eax
26439       3d/compare-eax-and 0/imm32/false
26440       74/jump-if-= break/disp8
26441       b8/copy-to-eax 1/imm32/true
26442       e9/jump $type-match?:end/disp32
26443     }
26444 $type-match?:baseline:
26445     # otherwise fall back
26446     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26447 $type-match?:end:
26448     # . epilogue
26449     89/<- %esp 5/r32/ebp
26450     5d/pop-to-ebp
26451     c3/return
26452 
26453 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26454     # . prologue
26455     55/push-ebp
26456     89/<- %ebp 4/r32/esp
26457     # . save registers
26458     51/push-ecx
26459     52/push-edx
26460     53/push-ebx
26461     # ecx = def
26462     8b/-> *(ebp+8) 1/r32/ecx
26463     # edx = call
26464     8b/-> *(ebp+0xc) 2/r32/edx
26465 $type-component-match?:compare-addr:
26466     # if (def == call) return true
26467     8b/-> %ecx 0/r32/eax  # Var-type
26468     39/compare %edx 0/r32/eax  # Var-type
26469     b8/copy-to-eax 1/imm32/true
26470     0f 84/jump-if-= $type-component-match?:end/disp32
26471     # if (def == 0) return false
26472     b8/copy-to-eax 0/imm32/false
26473     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
26474     0f 84/jump-if-= $type-component-match?:end/disp32
26475     # if (call == 0) return false
26476     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
26477     0f 84/jump-if-= $type-component-match?:end/disp32
26478     # if def is a type parameter, just check in type-parameters
26479     {
26480 $type-component-match?:check-type-parameter:
26481       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26482       74/jump-if-= break/disp8
26483       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
26484       75/jump-if-!= break/disp8
26485 $type-component-match?:type-parameter:
26486       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
26487       e9/jump $type-component-match?:end/disp32
26488     }
26489     # if def is a list containing just a type parameter, just check in type-parameters
26490     {
26491 $type-component-match?:check-list-type-parameter:
26492       # if def is a list..
26493       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26494       75/jump-if-!= break/disp8
26495       #   ..that's a singleton
26496       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
26497       75/jump-if-!= break/disp8
26498       #   ..and whose head is a type parameter
26499       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26500       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26501       74/jump-if-= break/disp8
26502       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
26503       75/jump-if-!= break/disp8
26504 $type-component-match?:list-type-parameter:
26505       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
26506       e9/jump $type-component-match?:end/disp32
26507     }
26508 $type-component-match?:compare-atom-state:
26509     # if (def->is-atom? != call->is-atom?) return false
26510     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26511     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26512     b8/copy-to-eax 0/imm32/false
26513     0f 85/jump-if-!= $type-component-match?:end/disp32
26514     # if def->is-atom? return (def->value == call->value)
26515     {
26516 $type-component-match?:check-atom:
26517       81 7/subop/compare %ebx 0/imm32/false
26518       74/jump-if-= break/disp8
26519 $type-component-match?:is-atom:
26520       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26521       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26522       0f 94/set-if-= %al
26523       25/and-eax-with 0xff/imm32
26524       e9/jump $type-component-match?:end/disp32
26525     }
26526 $type-component-match?:check-left:
26527     # if (!type-component-match?(def->left, call->left)) return false
26528     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26529     89/<- %ebx 0/r32/eax
26530     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26531     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26532     3d/compare-eax-and 0/imm32/false
26533     74/jump-if-= $type-component-match?:end/disp8
26534 $type-component-match?:check-right:
26535     # return type-component-match?(def->right, call->right)
26536     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26537     89/<- %ebx 0/r32/eax
26538     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26539     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
26540 $type-component-match?:end:
26541     # . restore registers
26542     5b/pop-to-ebx
26543     5a/pop-to-edx
26544     59/pop-to-ecx
26545     # . epilogue
26546     89/<- %esp 5/r32/ebp
26547     5d/pop-to-ebp
26548     c3/return
26549 
26550 type-parameter-match?:  # type-parameter-name: (handle array byte), type: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
26551     # . prologue
26552     55/push-ebp
26553     89/<- %ebp 4/r32/esp
26554     # . save registers
26555     51/push-ecx
26556     #
26557     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
26558     # if parameter wasn't saved, save it
26559     {
26560       81 7/subop/compare *eax 0/imm32
26561       75/jump-if-!= break/disp8
26562       8b/-> *(ebp+0x10) 1/r32/ecx
26563       89/<- *eax 1/r32/ecx
26564     }
26565     #
26566     (type-equal? *(ebp+0x10) *eax)  # => eax
26567 $type-parameter-match?:end:
26568     # . restore registers
26569     59/pop-to-ecx
26570     # . epilogue
26571     89/<- %esp 5/r32/ebp
26572     5d/pop-to-ebp
26573     c3/return
26574 
26575 size-of:  # v: (addr var) -> result/eax: int
26576     # . prologue
26577     55/push-ebp
26578     89/<- %ebp 4/r32/esp
26579     # . save registers
26580     51/push-ecx
26581     # var t/ecx: (addr type-tree) = lookup(v->type)
26582     8b/-> *(ebp+8) 1/r32/ecx
26583 #?     (write-buffered Stderr "size-of ")
26584 #?     (write-int32-hex-buffered Stderr %ecx)
26585 #?     (write-buffered Stderr Newline)
26586 #?     (write-buffered Stderr "type allocid: ")
26587 #?     (write-int32-hex-buffered Stderr *(ecx+8))
26588 #?     (write-buffered Stderr Newline)
26589 #?     (flush Stderr)
26590     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26591     89/<- %ecx 0/r32/eax
26592     # if mu-array?(t) return size-of-array(t)
26593     {
26594       (mu-array? %ecx)  # => eax
26595       3d/compare-eax-and 0/imm32/false
26596       74/jump-if-= break/disp8
26597       (size-of-array %ecx)  # => eax
26598       eb/jump $size-of:end/disp8
26599     }
26600     # if mu-stream?(t) return size-of-stream(t)
26601     {
26602       (mu-stream? %ecx)  # => eax
26603       3d/compare-eax-and 0/imm32/false
26604       74/jump-if-= break/disp8
26605       (size-of-stream %ecx)  # => eax
26606       eb/jump $size-of:end/disp8
26607     }
26608     # if (!t->is-atom?) t = lookup(t->left)
26609     {
26610       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26611       75/jump-if-!= break/disp8
26612       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26613       89/<- %ecx 0/r32/eax
26614     }
26615     # TODO: assert t->is-atom?
26616     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26617 $size-of:end:
26618     # . restore registers
26619     59/pop-to-ecx
26620     # . epilogue
26621     89/<- %esp 5/r32/ebp
26622     5d/pop-to-ebp
26623     c3/return
26624 
26625 size-of-deref:  # v: (addr var) -> result/eax: int
26626     # . prologue
26627     55/push-ebp
26628     89/<- %ebp 4/r32/esp
26629     # . save registers
26630     51/push-ecx
26631     # var t/ecx: (addr type-tree) = lookup(v->type)
26632     8b/-> *(ebp+8) 1/r32/ecx
26633     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26634     89/<- %ecx 0/r32/eax
26635     # TODO: assert(t is an addr)
26636     # t = lookup(t->right)
26637     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26638     89/<- %ecx 0/r32/eax
26639     # if mu-array?(t) return size-of-array(t)
26640     {
26641       (mu-array? %ecx)  # => eax
26642       3d/compare-eax-and 0/imm32/false
26643       74/jump-if-= break/disp8
26644       (size-of-array %ecx)  # => eax
26645       eb/jump $size-of-deref:end/disp8
26646     }
26647     # if mu-stream?(t) return size-of-stream(t)
26648     {
26649       (mu-stream? %ecx)  # => eax
26650       3d/compare-eax-and 0/imm32/false
26651       74/jump-if-= break/disp8
26652       (size-of-stream %ecx)  # => eax
26653       eb/jump $size-of-deref:end/disp8
26654     }
26655     # if (!t->is-atom?) t = lookup(t->left)
26656     {
26657       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26658       75/jump-if-!= break/disp8
26659       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26660       89/<- %ecx 0/r32/eax
26661     }
26662     # TODO: assert t->is-atom?
26663     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
26664 $size-of-deref:end:
26665     # . restore registers
26666     59/pop-to-ecx
26667     # . epilogue
26668     89/<- %esp 5/r32/ebp
26669     5d/pop-to-ebp
26670     c3/return
26671 
26672 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
26673     # . prologue
26674     55/push-ebp
26675     89/<- %ebp 4/r32/esp
26676     # . save registers
26677     51/push-ecx
26678     # ecx = t
26679     8b/-> *(ebp+8) 1/r32/ecx
26680     # if t->is-atom?, return false
26681     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26682     75/jump-if-!= $mu-array?:return-false/disp8
26683     # if !t->left->is-atom?, return false
26684     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26685     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26686     74/jump-if-= $mu-array?:return-false/disp8
26687     # return t->left->value == array
26688     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
26689     0f 94/set-if-= %al
26690     25/and-eax-with 0xff/imm32
26691     eb/jump $mu-array?:end/disp8
26692 $mu-array?:return-false:
26693     b8/copy-to-eax 0/imm32/false
26694 $mu-array?:end:
26695     # . restore registers
26696     59/pop-to-ecx
26697     # . epilogue
26698     89/<- %esp 5/r32/ebp
26699     5d/pop-to-ebp
26700     c3/return
26701 
26702 # size of a statically allocated array where the size is part of the type expression
26703 size-of-array:  # a: (addr type-tree) -> result/eax: int
26704     # . prologue
26705     55/push-ebp
26706     89/<- %ebp 4/r32/esp
26707     # . save registers
26708     51/push-ecx
26709     52/push-edx
26710     #
26711     8b/-> *(ebp+8) 1/r32/ecx
26712     # TODO: assert that a->left is 'array'
26713     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26714     89/<- %ecx 0/r32/eax
26715     # var elem-type/edx: type-id = a->right->left->value
26716     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26717     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
26718     # TODO: assert that a->right->right->left->value == size
26719     # var array-size/ecx: int = a->right->right->left->value-size
26720     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26721     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26722     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
26723     # return 4 + array-size * size-of(elem-type)
26724     (size-of-type-id-as-array-element %edx)  # => eax
26725     f7 4/subop/multiply-into-edx-eax %ecx
26726     05/add-to-eax 4/imm32  # for array size
26727     # TODO: check edx for overflow
26728 $size-of-array:end:
26729     # . restore registers
26730     5a/pop-to-edx
26731     59/pop-to-ecx
26732     # . epilogue
26733     89/<- %esp 5/r32/ebp
26734     5d/pop-to-ebp
26735     c3/return
26736 
26737 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
26738     # . prologue
26739     55/push-ebp
26740     89/<- %ebp 4/r32/esp
26741     # . save registers
26742     51/push-ecx
26743     # ecx = t
26744     8b/-> *(ebp+8) 1/r32/ecx
26745     # if t->is-atom?, return false
26746     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26747     75/jump-if-!= $mu-stream?:return-false/disp8
26748     # if !t->left->is-atom?, return false
26749     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26750     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26751     74/jump-if-= $mu-stream?:return-false/disp8
26752     # return t->left->value == stream
26753     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
26754     0f 94/set-if-= %al
26755     25/and-eax-with 0xff/imm32
26756     eb/jump $mu-stream?:end/disp8
26757 $mu-stream?:return-false:
26758     b8/copy-to-eax 0/imm32/false
26759 $mu-stream?:end:
26760     # . restore registers
26761     59/pop-to-ecx
26762     # . epilogue
26763     89/<- %esp 5/r32/ebp
26764     5d/pop-to-ebp
26765     c3/return
26766 
26767 # size of a statically allocated stream where the size is part of the type expression
26768 size-of-stream:  # a: (addr type-tree) -> result/eax: int
26769     # . prologue
26770     55/push-ebp
26771     89/<- %ebp 4/r32/esp
26772     #
26773     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
26774     05/add-to-eax 8/imm32  # for read/write pointers
26775 $size-of-stream:end:
26776     # . epilogue
26777     89/<- %esp 5/r32/ebp
26778     5d/pop-to-ebp
26779     c3/return
26780 
26781 size-of-type-id:  # t: type-id -> result/eax: int
26782     # . prologue
26783     55/push-ebp
26784     89/<- %ebp 4/r32/esp
26785     # . save registers
26786     51/push-ecx
26787     # var out/ecx: (handle typeinfo)
26788     68/push 0/imm32
26789     68/push 0/imm32
26790     89/<- %ecx 4/r32/esp
26791     # eax = t
26792     8b/-> *(ebp+8) 0/r32/eax
26793     # if t is a literal, return 0
26794     3d/compare-eax-and 0/imm32
26795     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
26796     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
26797     3d/compare-eax-and 8/imm32/byte
26798     {
26799       75/jump-if-!= break/disp8
26800       b8/copy-to-eax 4/imm32
26801       eb/jump $size-of-type-id:end/disp8
26802     }
26803     # if t is a handle, return 8
26804     3d/compare-eax-and 4/imm32/handle
26805     {
26806       75/jump-if-!= break/disp8
26807       b8/copy-to-eax 8/imm32
26808       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26809     }
26810     # if t is a slice, return 8
26811     3d/compare-eax-and 0xc/imm32/slice
26812     {
26813       75/jump-if-!= break/disp8
26814       b8/copy-to-eax 8/imm32
26815       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
26816     }
26817     # if t is a user-defined type, return its size
26818     # TODO: support non-atom type
26819     (find-typeinfo %eax %ecx)
26820     {
26821       81 7/subop/compare *ecx 0/imm32
26822       74/jump-if-= break/disp8
26823 $size-of-type-id:user-defined:
26824       (lookup *ecx *(ecx+4))  # => eax
26825       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
26826       eb/jump $size-of-type-id:end/disp8
26827     }
26828     # otherwise return the word size
26829     b8/copy-to-eax 4/imm32
26830 $size-of-type-id:end:
26831     # . reclaim locals
26832     81 0/subop/add %esp 8/imm32
26833     # . restore registers
26834     59/pop-to-ecx
26835     # . epilogue
26836     89/<- %esp 5/r32/ebp
26837     5d/pop-to-ebp
26838     c3/return
26839 
26840 # Minor violation of our type system since it returns an addr. But we could
26841 # replace it with a handle some time.
26842 # Returns null if t is an atom.
26843 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
26844     # . prologue
26845     55/push-ebp
26846     89/<- %ebp 4/r32/esp
26847     # . save registers
26848     51/push-ecx
26849     # eax = 0
26850     b8/copy-to-eax 0/imm32
26851     # ecx = t
26852     8b/-> *(ebp+8) 1/r32/ecx
26853 $type-tail:check-atom:
26854     # if t->is-atom? return 0
26855     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
26856     0f 85/jump-if-!= $type-tail:end/disp32
26857     # var tail = t->right
26858     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26859     89/<- %ecx 0/r32/eax
26860 $type-tail:check-singleton:
26861     # if (tail->right == 0) return tail->left
26862     {
26863       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
26864       75/jump-if-!= break/disp8
26865       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26866       e9/jump $type-tail:end/disp32
26867     }
26868     # if tail->right->left is an array-capacity, return tail->left
26869     {
26870 $type-tail:check-array-capacity:
26871       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26872       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26873       75/jump-if-!= break/disp8
26874 $type-tail:check-array-capacity-1:
26875       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26876       3d/compare-eax-and 0/imm32
26877       74/jump-if-= break/disp8
26878 $type-tail:check-array-capacity-2:
26879       (simple-mu-type? %eax 9)  # array-capacity => eax
26880       3d/compare-eax-and 0/imm32/false
26881       74/jump-if-= break/disp8
26882 $type-tail:array-capacity:
26883       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26884       eb/jump $type-tail:end/disp8
26885     }
26886 $type-tail:check-compound-left:
26887     # if !tail->left->is-atom? return tail->left
26888     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26889     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26890     74/jump-if-= $type-tail:end/disp8
26891 $type-tail:return-tail:
26892     # return tail
26893     89/<- %eax 1/r32/ecx
26894 $type-tail:end:
26895     # . restore registers
26896     59/pop-to-ecx
26897     # . epilogue
26898     89/<- %esp 5/r32/ebp
26899     5d/pop-to-ebp
26900     c3/return
26901 
26902 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
26903     # . prologue
26904     55/push-ebp
26905     89/<- %ebp 4/r32/esp
26906     # . save registers
26907     51/push-ecx
26908     52/push-edx
26909     53/push-ebx
26910     # ecx = a
26911     8b/-> *(ebp+8) 1/r32/ecx
26912     # edx = b
26913     8b/-> *(ebp+0xc) 2/r32/edx
26914 $type-equal?:compare-addr:
26915     # if (a == b) return true
26916     8b/-> %ecx 0/r32/eax  # Var-type
26917     39/compare %edx 0/r32/eax  # Var-type
26918     b8/copy-to-eax 1/imm32/true
26919     0f 84/jump-if-= $type-equal?:end/disp32
26920 $type-equal?:compare-null-a:
26921     # if (a == 0) return false
26922     b8/copy-to-eax 0/imm32/false
26923     81 7/subop/compare %ecx 0/imm32
26924     0f 84/jump-if-= $type-equal?:end/disp32
26925 $type-equal?:compare-null-b:
26926     # if (b == 0) return false
26927     81 7/subop/compare %edx 0/imm32
26928     0f 84/jump-if-= $type-equal?:end/disp32
26929 $type-equal?:compare-atom-state:
26930     # if (a->is-atom? != b->is-atom?) return false
26931     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
26932     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
26933     b8/copy-to-eax 0/imm32/false
26934     0f 85/jump-if-!= $type-equal?:end/disp32
26935     # if a->is-atom? return (a->value == b->value)
26936     {
26937 $type-equal?:check-atom:
26938       81 7/subop/compare %ebx 0/imm32/false
26939       74/jump-if-= break/disp8
26940 $type-equal?:is-atom:
26941       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
26942       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
26943       0f 94/set-if-= %al
26944       25/and-eax-with 0xff/imm32
26945       e9/jump $type-equal?:end/disp32
26946     }
26947 $type-equal?:check-left:
26948     # if (!type-equal?(a->left, b->left)) return false
26949     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
26950     89/<- %ebx 0/r32/eax
26951     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
26952     (type-equal? %eax %ebx)  # => eax
26953     3d/compare-eax-and 0/imm32/false
26954     74/jump-if-= $type-equal?:end/disp8
26955 $type-equal?:check-right:
26956     # return type-equal?(a->right, b->right)
26957     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
26958     89/<- %ebx 0/r32/eax
26959     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
26960     (type-equal? %eax %ebx)  # => eax
26961 $type-equal?:end:
26962     # . restore registers
26963     5b/pop-to-ebx
26964     5a/pop-to-edx
26965     59/pop-to-ecx
26966     # . epilogue
26967     89/<- %esp 5/r32/ebp
26968     5d/pop-to-ebp
26969     c3/return
26970 
26971 #######################################################
26972 # Code-generation
26973 #######################################################
26974 
26975 == data
26976 
26977 # Global state added to each var record when performing code-generation.
26978 Curr-local-stack-offset:  # (addr int)
26979     0/imm32
26980 
26981 == code
26982 
26983 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
26984 # getting type checks later in life.
26985 # But we do need them for runtime checks, particularly array index bounds checks.
26986 # So perhaps it's not worth taking them out. They're a safety net.
26987 
26988 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
26989     # . prologue
26990     55/push-ebp
26991     89/<- %ebp 4/r32/esp
26992     # . save registers
26993     50/push-eax
26994     # var curr/eax: (addr function) = *Program->functions
26995     (lookup *_Program-functions *_Program-functions->payload)  # => eax
26996     {
26997       # if (curr == null) break
26998       3d/compare-eax-and 0/imm32
26999       0f 84/jump-if-= break/disp32
27000       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
27001       # curr = lookup(curr->next)
27002       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
27003       e9/jump loop/disp32
27004     }
27005 $emit-subx:end:
27006     # . restore registers
27007     58/pop-to-eax
27008     # . epilogue
27009     89/<- %esp 5/r32/ebp
27010     5d/pop-to-ebp
27011     c3/return
27012 
27013 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27014     # . prologue
27015     55/push-ebp
27016     89/<- %ebp 4/r32/esp
27017     # some preprocessing
27018     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
27019     # . save registers
27020     50/push-eax
27021     51/push-ecx
27022     52/push-edx
27023     # initialize some global state
27024     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
27025     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
27026     # ecx = f
27027     8b/-> *(ebp+0xc) 1/r32/ecx
27028     # var vars/edx: (stack (addr var) 256)
27029     81 5/subop/subtract %esp 0xc00/imm32
27030     68/push 0xc00/imm32/size
27031     68/push 0/imm32/top
27032     89/<- %edx 4/r32/esp
27033     # var name/eax: (addr array byte) = lookup(f->name)
27034     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
27035     #
27036     (write-buffered *(ebp+8) %eax)
27037     (write-buffered *(ebp+8) ":\n")
27038     (emit-subx-prologue *(ebp+8))
27039     # var body/eax: (addr block) = lookup(f->body)
27040     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
27041     #
27042     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
27043     (emit-subx-epilogue *(ebp+8))
27044     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
27045     # been cleaned up
27046 $emit-subx-function:end:
27047     # . reclaim locals
27048     81 0/subop/add %esp 0xc08/imm32
27049     # . restore registers
27050     5a/pop-to-edx
27051     59/pop-to-ecx
27052     58/pop-to-eax
27053     # . epilogue
27054     89/<- %esp 5/r32/ebp
27055     5d/pop-to-ebp
27056     c3/return
27057 
27058 populate-mu-type-offsets-in-inouts:  # f: (addr function)
27059     # . prologue
27060     55/push-ebp
27061     89/<- %ebp 4/r32/esp
27062     # . save registers
27063     50/push-eax
27064     51/push-ecx
27065     52/push-edx
27066     53/push-ebx
27067     57/push-edi
27068     # var next-offset/edx: int = 8
27069     ba/copy-to-edx 8/imm32
27070     # var curr/ecx: (addr list var) = lookup(f->inouts)
27071     8b/-> *(ebp+8) 1/r32/ecx
27072     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
27073     89/<- %ecx 0/r32/eax
27074     {
27075 $populate-mu-type-offsets-in-inouts:loop:
27076       81 7/subop/compare %ecx 0/imm32
27077       74/jump-if-= break/disp8
27078       # var v/ebx: (addr var) = lookup(curr->value)
27079       (lookup *ecx *(ecx+4))  # List-value List-value => eax
27080       89/<- %ebx 0/r32/eax
27081 #?       (lookup *ebx *(ebx+4))
27082 #?       (write-buffered Stderr "setting offset of fn inout ")
27083 #?       (write-buffered Stderr %eax)
27084 #?       (write-buffered Stderr "@")
27085 #?       (write-int32-hex-buffered Stderr %ebx)
27086 #?       (write-buffered Stderr " to ")
27087 #?       (write-int32-hex-buffered Stderr %edx)
27088 #?       (write-buffered Stderr Newline)
27089 #?       (flush Stderr)
27090       # v->offset = next-offset
27091       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
27092       # next-offset += size-of(v)
27093       (size-of %ebx)  # => eax
27094       01/add-to %edx 0/r32/eax
27095       # curr = lookup(curr->next)
27096       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
27097       89/<- %ecx 0/r32/eax
27098       #
27099       eb/jump loop/disp8
27100     }
27101 $populate-mu-type-offsets-in-inouts:end:
27102     # . restore registers
27103     5f/pop-to-edi
27104     5b/pop-to-ebx
27105     5a/pop-to-edx
27106     59/pop-to-ecx
27107     58/pop-to-eax
27108     # . epilogue
27109     89/<- %esp 5/r32/ebp
27110     5d/pop-to-ebp
27111     c3/return
27112 
27113 emit-subx-stmt-list:  # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27114     # . prologue
27115     55/push-ebp
27116     89/<- %ebp 4/r32/esp
27117     # . save registers
27118     50/push-eax
27119     51/push-ecx
27120     53/push-ebx
27121     56/push-esi
27122     # esi = stmts
27123     8b/-> *(ebp+0xc) 6/r32/esi
27124     #
27125     {
27126 $emit-subx-stmt-list:loop:
27127       81 7/subop/compare %esi 0/imm32
27128       0f 84/jump-if-= break/disp32
27129       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
27130       (lookup *esi *(esi+4))  # List-value List-value => eax
27131       89/<- %ecx 0/r32/eax
27132       {
27133 $emit-subx-stmt-list:check-for-block:
27134         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
27135         75/jump-if-!= break/disp8
27136 $emit-subx-stmt-list:block:
27137         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27138       }
27139       {
27140 $emit-subx-stmt-list:check-for-stmt:
27141         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
27142         0f 85/jump-if-!= break/disp32
27143 $emit-subx-stmt-list:stmt1:
27144         {
27145           (mu-branch? %ecx)  # => eax
27146           3d/compare-eax-and 0/imm32/false
27147           0f 84/jump-if-= break/disp32
27148 $emit-subx-stmt-list:branch-stmt:
27149 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
27174 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
27201 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
27217 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
27255 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
27274         }
27275 $emit-subx-stmt-list:1-to-1:
27276         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27277         e9/jump $emit-subx-stmt-list:continue/disp32
27278       }
27279       {
27280 $emit-subx-stmt-list:check-for-var-def:
27281         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
27282         75/jump-if-!= break/disp8
27283 $emit-subx-stmt-list:var-def:
27284         (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
27285         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
27286         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
27287         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
27288         #
27289         eb/jump $emit-subx-stmt-list:continue/disp8
27290       }
27291       {
27292 $emit-subx-stmt-list:check-for-reg-var-def:
27293         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
27294         0f 85/jump-if-!= break/disp32
27295 $emit-subx-stmt-list:reg-var-def:
27296         # TODO: ensure that there's exactly one output
27297         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27298         # emit the instruction as usual
27299         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27300         #
27301         eb/jump $emit-subx-stmt-list:continue/disp8
27302       }
27303 $emit-subx-stmt-list:continue:
27304       # TODO: raise an error on unrecognized Stmt-tag
27305       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
27306       89/<- %esi 0/r32/eax
27307       e9/jump loop/disp32
27308     }
27309 $emit-subx-stmt-list:emit-cleanup:
27310     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
27311 $emit-subx-stmt-list:clean-up:
27312     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
27313     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
27314 $emit-subx-stmt-list:end:
27315     # . restore registers
27316     5e/pop-to-esi
27317     5b/pop-to-ebx
27318     59/pop-to-ecx
27319     58/pop-to-eax
27320     # . epilogue
27321     89/<- %esp 5/r32/ebp
27322     5d/pop-to-ebp
27323     c3/return
27324 
27325 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
27326 push-output-and-maybe-emit-spill:  # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27327     # . prologue
27328     55/push-ebp
27329     89/<- %ebp 4/r32/esp
27330     # . save registers
27331     50/push-eax
27332     51/push-ecx
27333     52/push-edx
27334     # ecx = stmt
27335     8b/-> *(ebp+0xc) 1/r32/ecx
27336     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
27337     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27338     # TODO: assert !sv->is-deref?
27339     # var v/ecx: (addr var) = lookup(sv->value)
27340     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27341     89/<- %ecx 0/r32/eax
27342     # v->block-depth = *Curr-block-depth
27343     8b/-> *Curr-block-depth 0/r32/eax
27344     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
27345 #?     (write-buffered Stderr "var ")
27346 #?     (lookup *ecx *(ecx+4))
27347 #?     (write-buffered Stderr %eax)
27348 #?     (write-buffered Stderr " at depth ")
27349 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
27350 #?     (write-buffered Stderr Newline)
27351 #?     (flush Stderr)
27352     # ensure that v is in a register
27353     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
27354     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
27355     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
27356     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
27357     89/<- %edx 0/r32/eax
27358     3d/compare-eax-and 0/imm32/false
27359     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27360     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
27361     89/<- %edx 0/r32/eax
27362     # check emit-spill?
27363     3d/compare-eax-and 0/imm32/false
27364     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
27365     # TODO: assert(size-of(output) == 4)
27366     # *Curr-local-stack-offset -= 4
27367     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
27368     # emit spill
27369     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
27370     (emit-push-register *(ebp+8) %eax)
27371 $push-output-and-maybe-emit-spill:push:
27372     8b/-> *(ebp+0xc) 1/r32/ecx
27373     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
27374     # push(vars, {sv->value, emit-spill?})
27375     (push *(ebp+0x10) *eax)  # Stmt-var-value
27376     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
27377     (push *(ebp+0x10) %edx)
27378 $push-output-and-maybe-emit-spill:end:
27379     # . restore registers
27380     5a/pop-to-edx
27381     59/pop-to-ecx
27382     58/pop-to-eax
27383     # . epilogue
27384     89/<- %esp 5/r32/ebp
27385     5d/pop-to-ebp
27386     c3/return
27387 
27388 $push-output-and-maybe-emit-spill:abort:
27389     # error("var '" var->name "' initialized from an instruction must live in a register\n")
27390     (write-buffered *(ebp+0x1c) "var '")
27391     (write-buffered *(ebp+0x1c) *eax)  # Var-name
27392     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
27393     (flush *(ebp+0x1c))
27394     (stop *(ebp+0x20) 1)
27395     # never gets here
27396 
27397 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
27398     # . prologue
27399     55/push-ebp
27400     89/<- %ebp 4/r32/esp
27401     # . save registers
27402     50/push-eax
27403     51/push-ecx
27404     # ecx = stmt
27405     8b/-> *(ebp+0xc) 1/r32/ecx
27406     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
27407     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27408     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27409     (lookup *eax *(eax+4))  # Var-name Var-name => eax
27410     # clean up until target block
27411     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
27412     # emit jump to target block
27413     (emit-indent *(ebp+8) *Curr-block-depth)
27414     (write-buffered *(ebp+8) "e9/jump ")
27415     (write-buffered *(ebp+8) %eax)
27416     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27417     (string-starts-with? %eax "break")
27418     3d/compare-eax-and 0/imm32/false
27419     {
27420       74/jump-if-= break/disp8
27421       (write-buffered *(ebp+8) ":break/disp32\n")
27422       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
27423     }
27424     (write-buffered *(ebp+8) ":loop/disp32\n")
27425 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
27426     # . restore registers
27427     59/pop-to-ecx
27428     58/pop-to-eax
27429     # . epilogue
27430     89/<- %esp 5/r32/ebp
27431     5d/pop-to-ebp
27432     c3/return
27433 
27434 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
27435     # . prologue
27436     55/push-ebp
27437     89/<- %ebp 4/r32/esp
27438     # . save registers
27439     50/push-eax
27440     51/push-ecx
27441     56/push-esi
27442     57/push-edi
27443     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
27444     8b/-> *(ebp+0xc) 0/r32/eax
27445     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27446     89/<- %esi 0/r32/eax
27447     # var curr-output/edi: (addr list var) = fn->outputs
27448     8b/-> *(ebp+0x10) 0/r32/eax
27449     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
27450     89/<- %edi 0/r32/eax
27451     {
27452 $emit-outputs:loop:
27453       81 7/subop/compare %esi 0/imm32
27454       0f 84/jump-if-= break/disp32
27455       # emit copy to output register
27456       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
27457       (lookup *edi *(edi+4))  # List-value List-value => eax
27458       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27459       89/<- %ecx 0/r32/eax
27460       # if curr-output-register starts with "x", emit a floating-point copy
27461       8a/copy-byte *(ecx+4) 0/r32/AL
27462       25/and-eax-with 0xff/imm32
27463       3d/compare-eax-and 0x78/imm32/x
27464       {
27465         75/jump-if-!= break/disp8
27466         (emit-float-output *(ebp+8) %esi %ecx)
27467         eb/jump $emit-outputs:continue/disp8
27468       }
27469       # otherwise emit an int copy
27470       (emit-int-output *(ebp+8) %esi %ecx)
27471 $emit-outputs:continue:
27472       # curr-inout = curr-inout->next
27473       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
27474       89/<- %esi 0/r32/eax
27475       # curr-output = curr-output->next
27476       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
27477       89/<- %edi 0/r32/eax
27478       #
27479       e9/jump loop/disp32
27480     }
27481 $emit-outputs:end:
27482     # . restore registers
27483     5f/pop-to-edi
27484     5e/pop-to-esi
27485     59/pop-to-ecx
27486     58/pop-to-eax
27487     # . epilogue
27488     89/<- %esp 5/r32/ebp
27489     5d/pop-to-ebp
27490     c3/return
27491 
27492 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27493     # . prologue
27494     55/push-ebp
27495     89/<- %ebp 4/r32/esp
27496     # . save registers
27497     50/push-eax
27498     51/push-ecx
27499     # ecx = return-var->value
27500     8b/-> *(ebp+0xc) 0/r32/eax
27501     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27502     89/<- %ecx 0/r32/eax
27503     # if curr-var is a literal, emit copy of a literal to the output
27504     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
27505     (simple-mu-type? %eax 0)  # literal => eax
27506     {
27507       3d/compare-eax-and 0/imm32/false
27508       0f 84/jump-if-= break/disp32
27509       (emit-indent *(ebp+8) *Curr-block-depth)
27510       (write-buffered *(ebp+8) "c7 0/subop/copy %")
27511       (write-buffered *(ebp+8) *(ebp+0x10))
27512       (write-buffered *(ebp+8) " ")
27513       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27514       (write-buffered *(ebp+8) %eax)
27515       (write-buffered *(ebp+8) "/imm32\n")
27516       e9/jump $emit-int-output:end/disp32
27517     }
27518     # otherwise emit an integer copy
27519     (emit-indent *(ebp+8) *Curr-block-depth)
27520     (write-buffered *(ebp+8) "8b/->")
27521     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27522     (write-buffered *(ebp+8) " ")
27523     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27524     (write-int32-hex-buffered *(ebp+8) *eax)
27525     (write-buffered *(ebp+8) "/r32\n")
27526 $emit-int-output:end:
27527     # . restore registers
27528     59/pop-to-ecx
27529     58/pop-to-eax
27530     # . epilogue
27531     89/<- %esp 5/r32/ebp
27532     5d/pop-to-ebp
27533     c3/return
27534 
27535 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
27536     # . prologue
27537     55/push-ebp
27538     89/<- %ebp 4/r32/esp
27539     # . save registers
27540     50/push-eax
27541     #
27542     (emit-indent *(ebp+8) *Curr-block-depth)
27543     (write-buffered *(ebp+8) "f3 0f 10/->")
27544     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
27545     (write-buffered *(ebp+8) " ")
27546     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
27547     (write-int32-hex-buffered *(ebp+8) *eax)
27548     (write-buffered *(ebp+8) "/x32\n")
27549 $emit-float-output:end:
27550     # . restore registers
27551     58/pop-to-eax
27552     # . epilogue
27553     89/<- %esp 5/r32/ebp
27554     5d/pop-to-ebp
27555     c3/return
27556 
27557 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
27558     # . prologue
27559     55/push-ebp
27560     89/<- %ebp 4/r32/esp
27561     # . save registers
27562     51/push-ecx
27563     # ecx = lookup(stmt->operation)
27564     8b/-> *(ebp+8) 1/r32/ecx
27565     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
27566     89/<- %ecx 0/r32/eax
27567     # if (stmt->operation starts with "loop") return true
27568     (string-starts-with? %ecx "loop")  # => eax
27569     3d/compare-eax-and 0/imm32/false
27570     75/jump-if-not-equal $mu-branch?:end/disp8
27571     # if (stmt->operation starts with "break") return true
27572     (string-starts-with? %ecx "break")  # => eax
27573     3d/compare-eax-and 0/imm32/false
27574     75/jump-if-not-equal $mu-branch?:end/disp8
27575     # otherwise return (stmt->operation starts with "return")
27576     (string-starts-with? %ecx "return")  # => eax
27577 $mu-branch?:end:
27578     # . restore registers
27579     59/pop-to-ecx
27580     # . epilogue
27581     89/<- %esp 5/r32/ebp
27582     5d/pop-to-ebp
27583     c3/return
27584 
27585 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
27586     # . prologue
27587     55/push-ebp
27588     89/<- %ebp 4/r32/esp
27589     # . save registers
27590     50/push-eax
27591     # eax = stmt
27592     8b/-> *(ebp+0xc) 0/r32/eax
27593     #
27594     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
27595     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
27596     (emit-indent *(ebp+8) *Curr-block-depth)
27597     (lookup *eax *(eax+4))  # => eax
27598     (write-buffered *(ebp+8) %eax)
27599     (write-buffered *(ebp+8) " break/disp32\n")
27600 $emit-reverse-break:end:
27601     # . restore registers
27602     58/pop-to-eax
27603     # . epilogue
27604     89/<- %esp 5/r32/ebp
27605     5d/pop-to-ebp
27606     c3/return
27607 
27608 == data
27609 
27610 # Table from Mu branch instructions to the reverse SubX opcodes for them.
27611 Reverse-branch:  # (table (handle array byte) (handle array byte))
27612   # a table is a stream
27613   0x240/imm32/write
27614   0/imm32/read
27615   0x240/imm32/size
27616   # data
27617   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27618   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
27619   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27620   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
27621   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27622   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
27623   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27624   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
27625   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27626   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
27627   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27628   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
27629   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27630   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27631   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27632   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27633   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27634   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27635   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27636   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27637   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27638   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27639   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27640   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
27641   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27642   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
27643   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27644   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27645   0x11/imm32/alloc-id   _string-break-if-carry/imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27646   0x11/imm32/alloc-id   _string-loop-if-carry/imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
27647   0x11/imm32/alloc-id   _string-break-if-not-carry/imm32        0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27648   0x11/imm32/alloc-id   _string-loop-if-not-carry/imm32         0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
27649   0x11/imm32/alloc-id   _string-break-if-overflow/imm32         0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
27650   0x11/imm32/alloc-id   _string-loop-if-overflow/imm32          0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
27651   0x11/imm32/alloc-id   _string-break-if-not-overflow/imm32     0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
27652   0x11/imm32/alloc-id   _string-loop-if-not-overflow/imm32      0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
27653 
27654 == code
27655 
27656 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
27657     # . prologue
27658     55/push-ebp
27659     89/<- %ebp 4/r32/esp
27660     # . save registers
27661     50/push-eax
27662     51/push-ecx
27663     52/push-edx
27664     53/push-ebx
27665     56/push-esi
27666     # ecx = vars
27667     8b/-> *(ebp+0xc) 1/r32/ecx
27668     # var eax: int = vars->top
27669     8b/-> *ecx 0/r32/eax
27670     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27671     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27672     # var min/ecx: (addr handle var) = vars->data
27673     8d/copy-address *(ecx+8) 1/r32/ecx
27674     # edx = depth
27675     8b/-> *(ebp+0x10) 2/r32/edx
27676     {
27677 $emit-unconditional-jump-to-depth:loop:
27678       # if (curr < min) break
27679       39/compare %esi 1/r32/ecx
27680       0f 82/jump-if-addr< break/disp32
27681       # var v/ebx: (addr var) = lookup(*curr)
27682       (lookup *esi *(esi+4))  # => eax
27683       89/<- %ebx 0/r32/eax
27684       # if (v->block-depth < until-block-depth) break
27685       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27686       0f 8c/jump-if-< break/disp32
27687       {
27688 $emit-unconditional-jump-to-depth:check:
27689         # if v->block-depth != until-block-depth, continue
27690         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27691         0f 85/jump-if-!= break/disp32
27692 $emit-unconditional-jump-to-depth:depth-found:
27693         # if v is not a literal, continue
27694         (size-of %ebx)  # => eax
27695         3d/compare-eax-and 0/imm32
27696         0f 85/jump-if-!= break/disp32
27697 $emit-unconditional-jump-to-depth:label-found:
27698         # emit unconditional jump, then return
27699         (emit-indent *(ebp+8) *Curr-block-depth)
27700         (write-buffered *(ebp+8) "e9/jump ")
27701         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27702         (write-buffered *(ebp+8) %eax)
27703         (write-buffered *(ebp+8) ":")
27704         (write-buffered *(ebp+8) *(ebp+0x14))
27705         (write-buffered *(ebp+8) "/disp32\n")
27706         eb/jump $emit-unconditional-jump-to-depth:end/disp8
27707       }
27708       # curr -= 12
27709       81 5/subop/subtract %esi 0xc/imm32
27710       e9/jump loop/disp32
27711     }
27712     # TODO: error if no label at 'depth' was found
27713 $emit-unconditional-jump-to-depth:end:
27714     # . restore registers
27715     5e/pop-to-esi
27716     5b/pop-to-ebx
27717     5a/pop-to-edx
27718     59/pop-to-ecx
27719     58/pop-to-eax
27720     # . epilogue
27721     89/<- %esp 5/r32/ebp
27722     5d/pop-to-ebp
27723     c3/return
27724 
27725 # emit clean-up code for 'vars' until some block depth
27726 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27727 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
27728     # . prologue
27729     55/push-ebp
27730     89/<- %ebp 4/r32/esp
27731     # . save registers
27732     50/push-eax
27733     51/push-ecx
27734     52/push-edx
27735     53/push-ebx
27736     56/push-esi
27737 #?     (write-buffered Stderr "--- cleanup\n")
27738 #?     (flush Stderr)
27739     # ecx = vars
27740     8b/-> *(ebp+0xc) 1/r32/ecx
27741     # var esi: int = vars->top
27742     8b/-> *ecx 6/r32/esi
27743     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27744     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27745     # var min/ecx: (addr handle var) = vars->data
27746     81 0/subop/add %ecx 8/imm32
27747     # edx = until-block-depth
27748     8b/-> *(ebp+0x10) 2/r32/edx
27749     {
27750 $emit-cleanup-code-until-depth:loop:
27751       # if (curr < min) break
27752       39/compare %esi 1/r32/ecx
27753       0f 82/jump-if-addr< break/disp32
27754       # var v/ebx: (addr var) = lookup(*curr)
27755       (lookup *esi *(esi+4))  # => eax
27756       89/<- %ebx 0/r32/eax
27757 #?       (lookup *ebx *(ebx+4))  # Var-name
27758 #?       (write-buffered Stderr "var ")
27759 #?       (write-buffered Stderr %eax)
27760 #?       (write-buffered Stderr Newline)
27761 #?       (flush Stderr)
27762       # if (v->block-depth < until-block-depth) break
27763       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
27764       0f 8c/jump-if-< break/disp32
27765       # if v is in a register
27766       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27767       {
27768         0f 84/jump-if-= break/disp32
27769         {
27770 $emit-cleanup-code-until-depth:check-for-previous-spill:
27771           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27772           3d/compare-eax-and 0/imm32/false
27773           74/jump-if-= break/disp8
27774 $emit-cleanup-code-until-depth:reclaim-var-in-register:
27775           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27776           (emit-pop-register *(ebp+8) %eax)
27777         }
27778         eb/jump $emit-cleanup-code-until-depth:continue/disp8
27779       }
27780       # otherwise v is on the stack
27781       {
27782         75/jump-if-!= break/disp8
27783 $emit-cleanup-code-until-depth:var-on-stack:
27784         (size-of %ebx)  # => eax
27785         # don't emit code for labels
27786         3d/compare-eax-and 0/imm32
27787         74/jump-if-= break/disp8
27788 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
27789         (emit-indent *(ebp+8) *Curr-block-depth)
27790         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27791         (write-int32-hex-buffered *(ebp+8) %eax)
27792         (write-buffered *(ebp+8) "/imm32\n")
27793       }
27794 $emit-cleanup-code-until-depth:continue:
27795       # curr -= 12
27796       81 5/subop/subtract %esi 0xc/imm32
27797       e9/jump loop/disp32
27798     }
27799 $emit-cleanup-code-until-depth:end:
27800     # . restore registers
27801     5e/pop-to-esi
27802     5b/pop-to-ebx
27803     5a/pop-to-edx
27804     59/pop-to-ecx
27805     58/pop-to-eax
27806     # . epilogue
27807     89/<- %esp 5/r32/ebp
27808     5d/pop-to-ebp
27809     c3/return
27810 
27811 # emit clean-up code for 'vars' that don't conflict with output registers
27812 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27813 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
27814     # . prologue
27815     55/push-ebp
27816     89/<- %ebp 4/r32/esp
27817     # . save registers
27818     50/push-eax
27819     51/push-ecx
27820     52/push-edx
27821     53/push-ebx
27822     56/push-esi
27823     57/push-edi
27824     # ecx = vars
27825     8b/-> *(ebp+0xc) 1/r32/ecx
27826     # var esi: int = vars->top
27827     8b/-> *ecx 6/r32/esi
27828     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
27829     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
27830     # var min/ecx: (addr handle var) = vars->data
27831     81 0/subop/add %ecx 8/imm32
27832     {
27833 $emit-cleanup-code-for-non-outputs:loop:
27834       # if (curr < min) break
27835       39/compare %esi 1/r32/ecx
27836       0f 82/jump-if-addr< break/disp32
27837       # var v/ebx: (addr var) = lookup(*curr)
27838       (lookup *esi *(esi+4))  # => eax
27839       89/<- %ebx 0/r32/eax
27840       # if v is in a register
27841       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
27842       {
27843         0f 84/jump-if-= break/disp32
27844         {
27845 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
27846           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
27847           3d/compare-eax-and 0/imm32/false
27848           0f 84/jump-if-= break/disp32
27849 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
27850           # var reg/edi: (addr array name) = v->register
27851           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27852           89/<- %edi 0/r32/eax
27853           # if reg is not in function outputs, emit a pop
27854           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
27855           3d/compare-eax-and 0/imm32/false
27856           {
27857             75/jump-if-!= break/disp8
27858             (emit-pop-register *(ebp+8) %edi)
27859             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
27860           }
27861           # otherwise just drop it from the stack
27862           (emit-indent *(ebp+8) *Curr-block-depth)
27863           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27864         }
27865 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
27866         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
27867       }
27868       # otherwise v is on the stack
27869       {
27870         75/jump-if-!= break/disp8
27871 $emit-cleanup-code-for-non-outputs:var-on-stack:
27872         (size-of %ebx)  # => eax
27873         # don't emit code for labels
27874         3d/compare-eax-and 0/imm32
27875         74/jump-if-= break/disp8
27876 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
27877         (emit-indent *(ebp+8) *Curr-block-depth)
27878         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
27879         (write-int32-hex-buffered *(ebp+8) %eax)
27880         (write-buffered *(ebp+8) "/imm32\n")
27881       }
27882 $emit-cleanup-code-for-non-outputs:continue:
27883       # curr -= 12
27884       81 5/subop/subtract %esi 0xc/imm32
27885       e9/jump loop/disp32
27886     }
27887 $emit-cleanup-code-for-non-outputs:end:
27888     # . restore registers
27889     5f/pop-to-edi
27890     5e/pop-to-esi
27891     5b/pop-to-ebx
27892     5a/pop-to-edx
27893     59/pop-to-ecx
27894     58/pop-to-eax
27895     # . epilogue
27896     89/<- %esp 5/r32/ebp
27897     5d/pop-to-ebp
27898     c3/return
27899 
27900 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
27901     # . prologue
27902     55/push-ebp
27903     89/<- %ebp 4/r32/esp
27904     # eax = reg
27905     8b/-> *(ebp+0xc) 0/r32/eax
27906     # var prefix/eax: byte = reg->data[0]
27907     8a/copy-byte *(eax+4) 0/r32/AL
27908     25/and-eax-with 0xff/imm32
27909     # if (prefix == 'x') push xmm register
27910     {
27911       3d/compare-eax-and 0x78/imm32/x
27912       0f 85/jump-if-!= break/disp32
27913       # TODO validate register
27914       (emit-indent *(ebp+8) *Curr-block-depth)
27915       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
27916       (emit-indent *(ebp+8) *Curr-block-depth)
27917       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
27918       # var prefix/eax: byte = reg->data[3]
27919       8b/-> *(ebp+0xc) 0/r32/eax
27920       8a/copy-byte *(eax+7) 0/r32/AL
27921       25/and-eax-with 0xff/imm32
27922       (write-byte-buffered *(ebp+8) %eax)
27923       (write-buffered *(ebp+8) "/x32\n")
27924       e9/jump $emit-push-register:end/disp32
27925     }
27926     # otherwise push gp register
27927     (emit-indent *(ebp+8) *Curr-block-depth)
27928     (write-buffered *(ebp+8) "ff 6/subop/push %")
27929     (write-buffered *(ebp+8) *(ebp+0xc))
27930     (write-buffered *(ebp+8) Newline)
27931 $emit-push-register:end:
27932     # . epilogue
27933     89/<- %esp 5/r32/ebp
27934     5d/pop-to-ebp
27935     c3/return
27936 
27937 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
27938     # . prologue
27939     55/push-ebp
27940     89/<- %ebp 4/r32/esp
27941     # . save registers
27942     50/push-eax
27943     # eax = reg
27944     8b/-> *(ebp+0xc) 0/r32/eax
27945     # var prefix/eax: byte = reg->data[0]
27946     8a/copy-byte *(eax+4) 0/r32/AL
27947     25/and-eax-with 0xff/imm32
27948     # if (prefix == 'x') pop to xmm register
27949     {
27950       3d/compare-eax-and 0x78/imm32/x
27951       0f 85/jump-if-!= break/disp32
27952       # TODO validate register
27953       (emit-indent *(ebp+8) *Curr-block-depth)
27954       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
27955       # var prefix/eax: byte = reg->data[3]
27956       8b/-> *(ebp+0xc) 0/r32/eax
27957       8a/copy-byte *(eax+7) 0/r32/AL
27958       25/and-eax-with 0xff/imm32
27959       (write-byte-buffered *(ebp+8) %eax)
27960       (write-buffered *(ebp+8) "/x32\n")
27961       (emit-indent *(ebp+8) *Curr-block-depth)
27962       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
27963       e9/jump $emit-pop-register:end/disp32
27964     }
27965     # otherwise pop to gp register
27966     (emit-indent *(ebp+8) *Curr-block-depth)
27967     (write-buffered *(ebp+8) "8f 0/subop/pop %")
27968     (write-buffered *(ebp+8) *(ebp+0xc))
27969     (write-buffered *(ebp+8) Newline)
27970 $emit-pop-register:end:
27971     # . restore registers
27972     58/pop-to-eax
27973     # . epilogue
27974     89/<- %esp 5/r32/ebp
27975     5d/pop-to-ebp
27976     c3/return
27977 
27978 # emit clean-up code for 'vars' until a given label is encountered
27979 # doesn't actually modify 'vars' so we need traverse manually inside the stack
27980 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
27981     # . prologue
27982     55/push-ebp
27983     89/<- %ebp 4/r32/esp
27984     # . save registers
27985     50/push-eax
27986     51/push-ecx
27987     52/push-edx
27988     53/push-ebx
27989     # ecx = vars
27990     8b/-> *(ebp+0xc) 1/r32/ecx
27991     # var eax: int = vars->top
27992     8b/-> *ecx 0/r32/eax
27993     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
27994     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
27995     # var min/ecx: (addr handle var) = vars->data
27996     81 0/subop/add %ecx 8/imm32
27997     {
27998 $emit-cleanup-code-until-target:loop:
27999       # if (curr < min) break
28000       39/compare %edx 1/r32/ecx
28001       0f 82/jump-if-addr< break/disp32
28002       # var v/ebx: (handle var) = lookup(*curr)
28003       (lookup *edx *(edx+4))  # => eax
28004       89/<- %ebx 0/r32/eax
28005       # if (v->name == until-block-label) break
28006       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
28007       (string-equal? %eax *(ebp+0x10))  # => eax
28008       3d/compare-eax-and 0/imm32/false
28009       0f 85/jump-if-!= break/disp32
28010       # if v is in a register
28011       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28012       {
28013         0f 84/jump-if-= break/disp32
28014         {
28015 $emit-cleanup-code-until-target:check-for-previous-spill:
28016           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
28017           3d/compare-eax-and 0/imm32/false
28018           74/jump-if-= break/disp8
28019 $emit-cleanup-code-until-target:reclaim-var-in-register:
28020           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
28021           (emit-pop-register *(ebp+8) %eax)
28022         }
28023         eb/jump $emit-cleanup-code-until-target:continue/disp8
28024       }
28025       # otherwise v is on the stack
28026       {
28027         75/jump-if-!= break/disp8
28028 $emit-cleanup-code-until-target:reclaim-var-on-stack:
28029         (size-of %ebx)  # => eax
28030         # don't emit code for labels
28031         3d/compare-eax-and 0/imm32
28032         74/jump-if-= break/disp8
28033         #
28034         (emit-indent *(ebp+8) *Curr-block-depth)
28035         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
28036         (write-int32-hex-buffered *(ebp+8) %eax)
28037         (write-buffered *(ebp+8) "/imm32\n")
28038       }
28039 $emit-cleanup-code-until-target:continue:
28040       # curr -= 12
28041       81 5/subop/subtract %edx 0xc/imm32
28042       e9/jump loop/disp32
28043     }
28044 $emit-cleanup-code-until-target:end:
28045     # . restore registers
28046     5b/pop-to-ebx
28047     5a/pop-to-edx
28048     59/pop-to-ecx
28049     58/pop-to-eax
28050     # . epilogue
28051     89/<- %esp 5/r32/ebp
28052     5d/pop-to-ebp
28053     c3/return
28054 
28055 # update Curr-local-stack-offset assuming vars until some block depth are popped
28056 # doesn't actually modify 'vars', so we need traverse manually inside the stack
28057 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
28058     # . prologue
28059     55/push-ebp
28060     89/<- %ebp 4/r32/esp
28061     # . save registers
28062     50/push-eax
28063     51/push-ecx
28064     52/push-edx
28065     53/push-ebx
28066     56/push-esi
28067     # ecx = vars
28068     8b/-> *(ebp+8) 1/r32/ecx
28069     # var esi: int = vars->top
28070     8b/-> *ecx 6/r32/esi
28071     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
28072     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
28073     # var min/ecx: (addr handle var) = vars->data
28074     81 0/subop/add %ecx 8/imm32
28075     # edx = until-block-depth
28076     8b/-> *(ebp+0xc) 2/r32/edx
28077     {
28078 $clean-up-stack-offset-state:loop:
28079       # if (curr < min) break
28080       39/compare %esi 1/r32/ecx
28081       0f 82/jump-if-addr< break/disp32
28082       # var v/ebx: (addr var) = lookup(*curr)
28083       (lookup *esi *(esi+4))  # => eax
28084       89/<- %ebx 0/r32/eax
28085       # if (v->block-depth < until-block-depth) break
28086       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
28087       0f 8c/jump-if-< break/disp32
28088       # if v is in a register
28089       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
28090       {
28091         0f 84/jump-if-= break/disp32
28092         {
28093 $clean-up-stack-offset-state:check-for-previous-spill:
28094           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
28095           3d/compare-eax-and 0/imm32/false
28096           74/jump-if-= break/disp8
28097 $clean-up-stack-offset-state:reclaim-var-in-register:
28098           81 0/subop/add *Curr-local-stack-offset 4/imm32
28099         }
28100         eb/jump $clean-up-stack-offset-state:continue/disp8
28101       }
28102       # otherwise v is on the stack
28103       {
28104         75/jump-if-!= break/disp8
28105 $clean-up-stack-offset-state:var-on-stack:
28106         (size-of %ebx)  # => eax
28107         01/add-to *Curr-local-stack-offset 0/r32/eax
28108       }
28109 $clean-up-stack-offset-state:continue:
28110       # curr -= 12
28111       81 5/subop/subtract %esi 0xc/imm32
28112       e9/jump loop/disp32
28113     }
28114 $clean-up-stack-offset-state:end:
28115     # . restore registers
28116     5e/pop-to-esi
28117     5b/pop-to-ebx
28118     5a/pop-to-edx
28119     59/pop-to-ecx
28120     58/pop-to-eax
28121     # . epilogue
28122     89/<- %esp 5/r32/ebp
28123     5d/pop-to-ebp
28124     c3/return
28125 
28126 # Return true if there isn't a variable in 'vars' with the same block-depth
28127 # and register as 'v'.
28128 # 'v' is guaranteed not to be within 'vars'.
28129 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
28130     # . prologue
28131     55/push-ebp
28132     89/<- %ebp 4/r32/esp
28133     # . save registers
28134     51/push-ecx
28135     52/push-edx
28136     53/push-ebx
28137     56/push-esi
28138     57/push-edi
28139     # ecx = vars
28140     8b/-> *(ebp+0xc) 1/r32/ecx
28141     # var eax: int = vars->top
28142     8b/-> *ecx 0/r32/eax
28143     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
28144     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
28145     # var min/ecx: (addr handle var) = vars->data
28146     8d/copy-address *(ecx+8) 1/r32/ecx
28147     # var depth/ebx: int = v->block-depth
28148     8b/-> *(ebp+8) 3/r32/ebx
28149     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
28150     # var needle/esi: (addr array byte) = v->register
28151     8b/-> *(ebp+8) 6/r32/esi
28152     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
28153     89/<- %esi 0/r32/eax
28154     {
28155 $not-yet-spilled-this-block?:loop:
28156       # if (curr < min) break
28157       39/compare %edx 1/r32/ecx
28158       0f 82/jump-if-addr< break/disp32
28159       # var cand/edi: (addr var) = lookup(*curr)
28160       (lookup *edx *(edx+4))  # => eax
28161       89/<- %edi 0/r32/eax
28162       # if (cand->block-depth < depth) break
28163       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
28164       0f 8c/jump-if-< break/disp32
28165       # var cand-reg/edi: (array array byte) = cand->reg
28166       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
28167       89/<- %edi 0/r32/eax
28168       # if (cand-reg == null) continue
28169       {
28170 $not-yet-spilled-this-block?:check-reg:
28171         81 7/subop/compare %edi 0/imm32
28172         0f 84/jump-if-= break/disp32
28173         # if (cand-reg == needle) return true
28174         (string-equal? %esi %edi)  # => eax
28175         3d/compare-eax-and 0/imm32/false
28176         74/jump-if-= break/disp8
28177 $not-yet-spilled-this-block?:return-false:
28178         b8/copy-to-eax 0/imm32/false
28179         eb/jump $not-yet-spilled-this-block?:end/disp8
28180       }
28181 $not-yet-spilled-this-block?:continue:
28182       # curr -= 12
28183       81 5/subop/subtract %edx 0xc/imm32
28184       e9/jump loop/disp32
28185     }
28186 $not-yet-spilled-this-block?:return-true:
28187     # return true
28188     b8/copy-to-eax 1/imm32/true
28189 $not-yet-spilled-this-block?:end:
28190     # . restore registers
28191     5f/pop-to-edi
28192     5e/pop-to-esi
28193     5b/pop-to-ebx
28194     5a/pop-to-edx
28195     59/pop-to-ecx
28196     # . epilogue
28197     89/<- %esp 5/r32/ebp
28198     5d/pop-to-ebp
28199     c3/return
28200 
28201 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
28202 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
28203     # . prologue
28204     55/push-ebp
28205     89/<- %ebp 4/r32/esp
28206     # eax = v
28207     8b/-> *(ebp+8) 0/r32/eax
28208     # var reg/eax: (addr array byte) = lookup(v->register)
28209     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28210     # var target/eax: (addr var) = find-register(fn-outputs, reg)
28211     (find-register *(ebp+0x10) %eax)  # => eax
28212     # if (target == 0) return true
28213     {
28214       3d/compare-eax-and 0/imm32
28215       75/jump-if-!= break/disp8
28216       b8/copy-to-eax 1/imm32/true
28217       eb/jump $will-not-write-some-register?:end/disp8
28218     }
28219     # return !assigns-in-stmts?(stmts, target)
28220     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
28221     3d/compare-eax-and 0/imm32/false
28222     # assume: true = 1, so no need to mask with 0x000000ff
28223     0f 94/set-if-= %al
28224 $will-not-write-some-register?:end:
28225     # . epilogue
28226     89/<- %esp 5/r32/ebp
28227     5d/pop-to-ebp
28228     c3/return
28229 
28230 # return fn output with matching register
28231 # always returns false if 'reg' is null
28232 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
28233     # . prologue
28234     55/push-ebp
28235     89/<- %ebp 4/r32/esp
28236     # . save registers
28237     51/push-ecx
28238     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28239     8b/-> *(ebp+8) 1/r32/ecx
28240     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
28241     89/<- %ecx 0/r32/eax
28242     {
28243 $find-register:loop:
28244       # if (curr == 0) break
28245       81 7/subop/compare %ecx 0/imm32
28246       74/jump-if-= break/disp8
28247       # eax = curr->value->register
28248       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28249       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28250       # if (eax == reg) return curr->value
28251 $find-register:compare:
28252       (string-equal? *(ebp+0xc) %eax)  # => eax
28253       {
28254         3d/compare-eax-and 0/imm32/false
28255         74/jump-if-= break/disp8
28256 $find-register:found:
28257         (lookup *ecx *(ecx+4))  # List-value List-value => eax
28258         eb/jump $find-register:end/disp8
28259       }
28260       # curr = lookup(curr->next)
28261       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28262       89/<- %ecx 0/r32/eax
28263       #
28264       eb/jump loop/disp8
28265     }
28266 $find-register:end:
28267     # . restore registers
28268     59/pop-to-ecx
28269     # . epilogue
28270     89/<- %esp 5/r32/ebp
28271     5d/pop-to-ebp
28272     c3/return
28273 
28274 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
28275     # . prologue
28276     55/push-ebp
28277     89/<- %ebp 4/r32/esp
28278     # . save registers
28279     51/push-ecx
28280     # var curr/ecx: (addr list stmt) = stmts
28281     8b/-> *(ebp+8) 1/r32/ecx
28282     {
28283       # if (curr == 0) break
28284       81 7/subop/compare %ecx 0/imm32
28285       74/jump-if-= break/disp8
28286       # if assigns-in-stmt?(curr->value, v) return true
28287       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28288       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
28289       3d/compare-eax-and 0/imm32/false
28290       75/jump-if-!= break/disp8
28291       # curr = lookup(curr->next)
28292       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28293       89/<- %ecx 0/r32/eax
28294       #
28295       eb/jump loop/disp8
28296     }
28297 $assigns-in-stmts?:end:
28298     # . restore registers
28299     59/pop-to-ecx
28300     # . epilogue
28301     89/<- %esp 5/r32/ebp
28302     5d/pop-to-ebp
28303     c3/return
28304 
28305 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
28306     # . prologue
28307     55/push-ebp
28308     89/<- %ebp 4/r32/esp
28309     # . save registers
28310     51/push-ecx
28311     # ecx = stmt
28312     8b/-> *(ebp+8) 1/r32/ecx
28313     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
28314     {
28315       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
28316       75/jump-if-!= break/disp8
28317       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28318       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
28319       eb/jump $assigns-in-stmt?:end/disp8
28320     }
28321     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
28322     {
28323       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
28324       75/jump-if-!= break/disp8
28325       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
28326       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
28327       eb/jump $assigns-in-stmt?:end/disp8
28328     }
28329     # otherwise return false
28330     b8/copy 0/imm32/false
28331 $assigns-in-stmt?:end:
28332     # . restore registers
28333     59/pop-to-ecx
28334     # . epilogue
28335     89/<- %esp 5/r32/ebp
28336     5d/pop-to-ebp
28337     c3/return
28338 
28339 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
28340     # . prologue
28341     55/push-ebp
28342     89/<- %ebp 4/r32/esp
28343     # . save registers
28344     51/push-ecx
28345     # var curr/ecx: (addr stmt-var) = stmt-var
28346     8b/-> *(ebp+8) 1/r32/ecx
28347     {
28348       # if (curr == 0) break
28349       81 7/subop/compare %ecx 0/imm32
28350       74/jump-if-= break/disp8
28351       # eax = lookup(curr->value)
28352       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
28353       # if (eax == v  &&  curr->is-deref? == false) return true
28354       {
28355         39/compare *(ebp+0xc) 0/r32/eax
28356         75/jump-if-!= break/disp8
28357         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
28358         75/jump-if-!= break/disp8
28359         b8/copy-to-eax 1/imm32/true
28360         eb/jump $assigns-in-stmt-vars?:end/disp8
28361       }
28362       # curr = lookup(curr->next)
28363       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
28364       89/<- %ecx 0/r32/eax
28365       #
28366       eb/jump loop/disp8
28367     }
28368 $assigns-in-stmt-vars?:end:
28369     # . restore registers
28370     59/pop-to-ecx
28371     # . epilogue
28372     89/<- %esp 5/r32/ebp
28373     5d/pop-to-ebp
28374     c3/return
28375 
28376 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
28377 # v is guaranteed to be within vars
28378 # 'start' is provided as an optimization, a pointer within vars
28379 # *start == v
28380 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
28381     # . prologue
28382     55/push-ebp
28383     89/<- %ebp 4/r32/esp
28384     # . save registers
28385     51/push-ecx
28386     52/push-edx
28387     53/push-ebx
28388     56/push-esi
28389     57/push-edi
28390     # ecx = v
28391     8b/-> *(ebp+8) 1/r32/ecx
28392     # var reg/edx: (addr array byte) = lookup(v->register)
28393     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
28394     89/<- %edx 0/r32/eax
28395     # var depth/ebx: int = v->block-depth
28396     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
28397     # var min/ecx: (addr handle var) = vars->data
28398     8b/-> *(ebp+0xc) 1/r32/ecx
28399     81 0/subop/add %ecx 8/imm32
28400     # TODO: check that start >= min and start < &vars->data[top]
28401     # TODO: check that *start == v
28402     # var curr/esi: (addr handle var) = start
28403     8b/-> *(ebp+0x10) 6/r32/esi
28404     # curr -= 8
28405     81 5/subop/subtract %esi 8/imm32
28406     {
28407 $same-register-spilled-before?:loop:
28408       # if (curr < min) break
28409       39/compare %esi 1/r32/ecx
28410       0f 82/jump-if-addr< break/disp32
28411       # var x/eax: (addr var) = lookup(*curr)
28412       (lookup *esi *(esi+4))  # => eax
28413       # if (x->block-depth < depth) break
28414       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
28415       0f 8c/jump-if-< break/disp32
28416       # if (x->register == 0) continue
28417       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
28418       74/jump-if-= $same-register-spilled-before?:continue/disp8
28419       # if (x->register == reg) return true
28420       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28421       (string-equal? %eax %edx)  # => eax
28422       3d/compare-eax-and 0/imm32/false
28423       b8/copy-to-eax 1/imm32/true
28424       75/jump-if-!= $same-register-spilled-before?:end/disp8
28425 $same-register-spilled-before?:continue:
28426       # curr -= 8
28427       81 5/subop/subtract %esi 8/imm32
28428       e9/jump loop/disp32
28429     }
28430 $same-register-spilled-before?:false:
28431     b8/copy-to-eax 0/imm32/false
28432 $same-register-spilled-before?:end:
28433     # . restore registers
28434     5f/pop-to-edi
28435     5e/pop-to-esi
28436     5b/pop-to-ebx
28437     5a/pop-to-edx
28438     59/pop-to-ecx
28439     # . epilogue
28440     89/<- %esp 5/r32/ebp
28441     5d/pop-to-ebp
28442     c3/return
28443 
28444 # clean up global state for 'vars' until some block depth (inclusive)
28445 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
28446     # . prologue
28447     55/push-ebp
28448     89/<- %ebp 4/r32/esp
28449     # . save registers
28450     50/push-eax
28451     51/push-ecx
28452     56/push-esi
28453     # esi = vars
28454     8b/-> *(ebp+8) 6/r32/esi
28455     # ecx = until-block-depth
28456     8b/-> *(ebp+0xc) 1/r32/ecx
28457     {
28458 $clean-up-blocks:reclaim-loop:
28459       # if (vars->top <= 0) break
28460       8b/-> *esi 0/r32/eax  # Stack-top
28461       3d/compare-eax-and 0/imm32
28462       0f 8e/jump-if-<= break/disp32
28463       # var v/eax: (addr var) = lookup(vars[vars->top-12])
28464       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
28465       # if (v->block-depth < until-block-depth) break
28466       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
28467       0f 8c/jump-if-< break/disp32
28468       (pop %esi)  # => eax
28469       (pop %esi)  # => eax
28470       (pop %esi)  # => eax
28471       e9/jump loop/disp32
28472     }
28473 $clean-up-blocks:end:
28474     # . restore registers
28475     5e/pop-to-esi
28476     59/pop-to-ecx
28477     58/pop-to-eax
28478     # . epilogue
28479     89/<- %esp 5/r32/ebp
28480     5d/pop-to-ebp
28481     c3/return
28482 
28483 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
28484     # . prologue
28485     55/push-ebp
28486     89/<- %ebp 4/r32/esp
28487     # . save registers
28488     51/push-ecx
28489     # var curr/ecx: (addr list var) = lookup(fn->outputs)
28490     8b/-> *(ebp+8) 0/r32/eax
28491     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
28492     89/<- %ecx 0/r32/eax
28493     # while curr != null
28494     {
28495       81 7/subop/compare %ecx 0/imm32
28496       74/jump-if-= break/disp8
28497       # var v/eax: (addr var) = lookup(curr->value)
28498       (lookup *ecx *(ecx+4))  # List-value List-value => eax
28499       # var reg/eax: (addr array byte) = lookup(v->register)
28500       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28501       # if (reg == target) return true
28502       (string-equal? %eax *(ebp+0xc))  # => eax
28503       3d/compare-eax-and 0/imm32/false
28504       75/jump-if-!= $reg-in-function-outputs?:end/disp8
28505       # curr = curr->next
28506       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
28507       89/<- %ecx 0/r32/eax
28508       #
28509       eb/jump loop/disp8
28510     }
28511     # return false
28512     b8/copy-to-eax 0/imm32
28513 $reg-in-function-outputs?:end:
28514     # . restore registers
28515     59/pop-to-ecx
28516     # . epilogue
28517     89/<- %esp 5/r32/ebp
28518     5d/pop-to-ebp
28519     c3/return
28520 
28521 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28522     # . prologue
28523     55/push-ebp
28524     89/<- %ebp 4/r32/esp
28525     # . save registers
28526     50/push-eax
28527     51/push-ecx
28528     52/push-edx
28529     # eax = stmt
28530     8b/-> *(ebp+0xc) 0/r32/eax
28531     # var v/ecx: (addr var)
28532     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
28533     89/<- %ecx 0/r32/eax
28534     # v->block-depth = *Curr-block-depth
28535     8b/-> *Curr-block-depth 0/r32/eax
28536     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
28537     # var n/edx: int = size-of(stmt->var)
28538     (size-of %ecx)  # => eax
28539     89/<- %edx 0/r32/eax
28540     # *Curr-local-stack-offset -= n
28541     29/subtract-from *Curr-local-stack-offset 2/r32/edx
28542     # v->offset = *Curr-local-stack-offset
28543     8b/-> *Curr-local-stack-offset 0/r32/eax
28544     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
28545     # if v is an array, do something special to initialize it
28546     {
28547       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28548       (mu-array? %eax)  # => eax
28549       3d/compare-eax-and 0/imm32/false
28550       0f 84/jump-if-= break/disp32
28551       # var array-size-without-size/edx: int = n-4
28552       81 5/subop/subtract %edx 4/imm32
28553       #
28554       (emit-array-data-initialization *(ebp+8) %edx)
28555       e9/jump $emit-subx-var-def:end/disp32
28556     }
28557     # another special-case for initializing streams
28558     # a stream is an array with 2 extra pointers
28559     {
28560       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28561       (mu-stream? %eax)  # => eax
28562       3d/compare-eax-and 0/imm32/false
28563       0f 84/jump-if-= break/disp32
28564       # var array-size-without-size/edx: int = n-12
28565       81 5/subop/subtract %edx 0xc/imm32
28566       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
28567       (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
28568       # emit read and write pointers
28569       (emit-indent *(ebp+8) *Curr-block-depth)
28570       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28571       (emit-indent *(ebp+8) *Curr-block-depth)
28572       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28573       #
28574       eb/jump $emit-subx-var-def:end/disp8
28575     }
28576     # while n > 0
28577     {
28578       81 7/subop/compare %edx 0/imm32
28579       7e/jump-if-<= break/disp8
28580       (emit-indent *(ebp+8) *Curr-block-depth)
28581       (write-buffered *(ebp+8) "68/push 0/imm32\n")
28582       # n -= 4
28583       81 5/subop/subtract %edx 4/imm32
28584       #
28585       eb/jump loop/disp8
28586     }
28587 $emit-subx-var-def:end:
28588     # . restore registers
28589     5a/pop-to-edx
28590     59/pop-to-ecx
28591     58/pop-to-eax
28592     # . epilogue
28593     89/<- %esp 5/r32/ebp
28594     5d/pop-to-ebp
28595     c3/return
28596 
28597 emit-array-data-initialization:  # out: (addr buffered-file), n: int
28598     # . prologue
28599     55/push-ebp
28600     89/<- %ebp 4/r32/esp
28601     #
28602     (emit-indent *(ebp+8) *Curr-block-depth)
28603     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28604     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28605     (write-buffered *(ebp+8) ")\n")
28606     (emit-indent *(ebp+8) *Curr-block-depth)
28607     (write-buffered *(ebp+8) "68/push ")
28608     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28609     (write-buffered *(ebp+8) "/imm32\n")
28610 $emit-array-data-initialization:end:
28611     # . epilogue
28612     89/<- %esp 5/r32/ebp
28613     5d/pop-to-ebp
28614     c3/return
28615 
28616 emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
28617     # . prologue
28618     55/push-ebp
28619     89/<- %ebp 4/r32/esp
28620     # . save registers
28621     50/push-eax
28622     # Optimization: if it's a stream of bytes, don't initialize.
28623     #
28624     # We often construct large temporary streams on the stack for 'trace'
28625     # statements. Initializing such streams can significantly slow programs
28626     # down.
28627     #
28628     # Mu doesn't really depend on initializing stream contents for type- or
28629     # memory-safety; we're mostly doing so to make it easy to debug unsafe
28630     # SubX code that misuses stream objects by manipulating read/write
28631     # pointers. But you can't _really_ protect from unsafe SubX, so I think we
28632     # don't give up much safety or security here.
28633     {
28634       (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
28635       3d/compare-eax-and 8/imm32/byte
28636       75/jump-if-!= break/disp8
28637       (emit-indent *(ebp+8) *Curr-block-depth)
28638       (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
28639       (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28640       (write-buffered *(ebp+8) "/imm32\n")
28641       eb/jump $emit-stream-data-initialization:emit-length/disp8
28642     }
28643     (emit-indent *(ebp+8) *Curr-block-depth)
28644     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
28645     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28646     (write-buffered *(ebp+8) ")\n")
28647 $emit-stream-data-initialization:emit-length:
28648     (emit-indent *(ebp+8) *Curr-block-depth)
28649     (write-buffered *(ebp+8) "68/push ")
28650     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
28651     (write-buffered *(ebp+8) "/imm32\n")
28652 $emit-stream-data-initialization:end:
28653     # . restore registers
28654     58/pop-to-eax
28655     # . epilogue
28656     89/<- %esp 5/r32/ebp
28657     5d/pop-to-ebp
28658     c3/return
28659 
28660 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
28661     # . prologue
28662     55/push-ebp
28663     89/<- %ebp 4/r32/esp
28664     # . save registers
28665     50/push-eax
28666     51/push-ecx
28667     # - some special-case primitives that don't actually use the 'primitives' data structure
28668     # var op/ecx: (addr array byte) = lookup(stmt->operation)
28669     8b/-> *(ebp+0xc) 1/r32/ecx
28670     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
28671     89/<- %ecx 0/r32/eax
28672     # copy byte (can be a primitive except we need to emit a second instruction)
28673     {
28674       # if (!string-equal?(stmt->operation, "copy-byte")) break
28675       (string-equal? %ecx "copy-byte")  # => eax
28676       3d/compare-eax-and 0/imm32/false
28677       0f 84/jump-if-= break/disp32
28678       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28679       e9/jump $emit-subx-stmt:end/disp32
28680     }
28681     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
28682     # array size
28683     {
28684       # if (!string-equal?(stmt->operation, "length")) break
28685       (string-equal? %ecx "length")  # => eax
28686       3d/compare-eax-and 0/imm32/false
28687       0f 84/jump-if-= break/disp32
28688       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28689       e9/jump $emit-subx-stmt:end/disp32
28690     }
28691     # index into array
28692     {
28693       # if (!string-equal?(stmt->operation, "index")) break
28694       (string-equal? %ecx "index")  # => eax
28695       3d/compare-eax-and 0/imm32/false
28696       0f 84/jump-if-= break/disp32
28697       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
28698       e9/jump $emit-subx-stmt:end/disp32
28699     }
28700     # compute-offset for index into array
28701     {
28702       # if (!string-equal?(stmt->operation, "compute-offset")) break
28703       (string-equal? %ecx "compute-offset")  # => eax
28704       3d/compare-eax-and 0/imm32/false
28705       0f 84/jump-if-= break/disp32
28706       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28707       e9/jump $emit-subx-stmt:end/disp32
28708     }
28709     # get field from record
28710     {
28711       # if (!string-equal?(stmt->operation, "get")) break
28712       (string-equal? %ecx "get")  # => eax
28713       3d/compare-eax-and 0/imm32/false
28714       0f 84/jump-if-= break/disp32
28715       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
28716       e9/jump $emit-subx-stmt:end/disp32
28717     }
28718     # allocate scalar
28719     {
28720       # if (!string-equal?(stmt->operation, "allocate")) break
28721       (string-equal? %ecx "allocate")  # => eax
28722       3d/compare-eax-and 0/imm32/false
28723       0f 84/jump-if-= break/disp32
28724       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28725       e9/jump $emit-subx-stmt:end/disp32
28726     }
28727     # copy-object
28728     {
28729       # if (!string-equal?(stmt->operation, "copy-object")) break
28730       (string-equal? %ecx "copy-object")  # => eax
28731       3d/compare-eax-and 0/imm32/false
28732       0f 84/jump-if-= break/disp32
28733       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28734       e9/jump $emit-subx-stmt:end/disp32
28735     }
28736     # clear-object
28737     {
28738       # if (!string-equal?(stmt->operation, "clear-object")) break
28739       (string-equal? %ecx "clear-object")  # => eax
28740       3d/compare-eax-and 0/imm32/false
28741       0f 84/jump-if-= break/disp32
28742       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28743       e9/jump $emit-subx-stmt:end/disp32
28744     }
28745     # allocate array
28746     {
28747       # if (!string-equal?(stmt->operation, "populate")) break
28748       (string-equal? %ecx "populate")  # => eax
28749       3d/compare-eax-and 0/imm32/false
28750       0f 84/jump-if-= break/disp32
28751       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28752       e9/jump $emit-subx-stmt:end/disp32
28753     }
28754     # allocate stream
28755     {
28756       # if (!string-equal?(stmt->operation, "populate-stream")) break
28757       (string-equal? %ecx "populate-stream")  # => eax
28758       3d/compare-eax-and 0/imm32/false
28759       0f 84/jump-if-= break/disp32
28760       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28761       e9/jump $emit-subx-stmt:end/disp32
28762     }
28763     # read from stream
28764     {
28765       # if (!string-equal?(stmt->operation, "read-from-stream")) break
28766       (string-equal? %ecx "read-from-stream")  # => eax
28767       3d/compare-eax-and 0/imm32/false
28768       0f 84/jump-if-= break/disp32
28769       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28770       e9/jump $emit-subx-stmt:end/disp32
28771     }
28772     # write to stream
28773     {
28774       # if (!string-equal?(stmt->operation, "write-to-stream")) break
28775       (string-equal? %ecx "write-to-stream")  # => eax
28776       3d/compare-eax-and 0/imm32/false
28777       0f 84/jump-if-= break/disp32
28778       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
28779       e9/jump $emit-subx-stmt:end/disp32
28780     }
28781     # - optimizations
28782     # if copy instruction has same register in source and destination, emit nothing
28783     (redundant-copy? *(ebp+0xc))  # => eax
28784     3d/compare-eax-and 0/imm32/false
28785     75/jump-if-!= $emit-subx-stmt:end/disp8
28786     # - if stmt matches a primitive, emit it
28787     {
28788 $emit-subx-stmt:check-for-primitive:
28789       # var curr/eax: (addr primitive)
28790       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
28791       3d/compare-eax-and 0/imm32
28792       74/jump-if-= break/disp8
28793 $emit-subx-stmt:primitive:
28794       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
28795       e9/jump $emit-subx-stmt:end/disp32
28796     }
28797     # - otherwise emit a call
28798     # TODO: type-checking
28799 $emit-subx-stmt:call:
28800     (emit-call *(ebp+8) *(ebp+0xc))
28801 $emit-subx-stmt:end:
28802     # . restore registers
28803     59/pop-to-ecx
28804     58/pop-to-eax
28805     # . epilogue
28806     89/<- %esp 5/r32/ebp
28807     5d/pop-to-ebp
28808     c3/return
28809 
28810 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
28811     # . prologue
28812     55/push-ebp
28813     89/<- %ebp 4/r32/esp
28814     # . save registers
28815     56/push-esi
28816     57/push-edi
28817     # esi = stmt
28818     8b/-> *(ebp+8) 6/r32/esi
28819     # if stmt->operation != "copy" return false
28820     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
28821     (string-equal? %eax "copy")  # => eax
28822     3d/compare-eax-and 0/imm32/false
28823     0f 84/jump-if-= $redundant-copy?:end/disp32
28824     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
28825     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28826     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28827     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28828     # . if output-reg == null, return false
28829     3d/compare-eax-and 0/imm32
28830     74/jump-if-= $redundant-copy?:end/disp8
28831     89/<- %edi 0/r32/eax
28832     # return (inout->value->register == output->value->register)
28833     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28834     # . if inout->is-deref return false
28835     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
28836     {
28837       74/jump-if-= break/disp8
28838       b8/copy-to-eax 0/imm32/false
28839       e9/jump $redundant-copy?:end/disp32
28840     }
28841     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28842     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28843     # . if inout-reg == null, return false
28844     3d/compare-eax-and 0/imm32
28845     74/jump-if-= $redundant-copy?:end/disp8
28846     (string-equal? %eax %edi)  # => eax
28847 $redundant-copy?:end:
28848     # . restore registers
28849     5f/pop-to-edi
28850     5e/pop-to-esi
28851     # . epilogue
28852     89/<- %esp 5/r32/ebp
28853     5d/pop-to-ebp
28854     c3/return
28855 
28856 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
28857     # . prologue
28858     55/push-ebp
28859     89/<- %ebp 4/r32/esp
28860     # . save registers
28861     50/push-eax
28862     51/push-ecx
28863     52/push-edx
28864     53/push-ebx
28865     56/push-esi
28866     # esi = stmt
28867     8b/-> *(ebp+0xc) 6/r32/esi
28868     # var base/ebx: (addr var) = stmt->inouts[0]->value
28869     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
28870     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28871     89/<- %ebx 0/r32/eax
28872     # var elemsize/ecx: int = array-element-size(base)
28873     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
28874     89/<- %ecx 0/r32/eax
28875     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
28876     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
28877     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
28878     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
28879     89/<- %edx 0/r32/eax
28880     # if elemsize == 1
28881     {
28882       81 7/subop/compare %ecx 1/imm32
28883       75/jump-if-!= break/disp8
28884 $translate-mu-length-stmt:size-1:
28885       (emit-save-size-to *(ebp+8) %ebx %edx)
28886       e9/jump $translate-mu-length-stmt:end/disp32
28887     }
28888     # if elemsize is a power of 2 less than 256
28889     {
28890       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
28891       3d/compare-eax-and 0/imm32/false
28892       74/jump-if-= break/disp8
28893       81 7/subop/compare %ecx 0xff/imm32
28894       7f/jump-if-> break/disp8
28895 $translate-mu-length-stmt:size-power-of-2:
28896       (emit-save-size-to *(ebp+8) %ebx %edx)
28897       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
28898       e9/jump $translate-mu-length-stmt:end/disp32
28899     }
28900     # otherwise, the complex case
28901     # . emit register spills
28902     {
28903 $translate-mu-length-stmt:complex:
28904       (string-equal? %edx "eax")  # => eax
28905       3d/compare-eax-and 0/imm32/false
28906       75/break-if-!= break/disp8
28907       (emit-indent *(ebp+8) *Curr-block-depth)
28908       (write-buffered *(ebp+8) "50/push-eax\n")
28909     }
28910     {
28911       (string-equal? %edx "ecx")  # => eax
28912       3d/compare-eax-and 0/imm32/false
28913       75/break-if-!= break/disp8
28914       (emit-indent *(ebp+8) *Curr-block-depth)
28915       (write-buffered *(ebp+8) "51/push-ecx\n")
28916     }
28917     {
28918       (string-equal? %edx "edx")  # => eax
28919       3d/compare-eax-and 0/imm32/false
28920       75/break-if-!= break/disp8
28921       (emit-indent *(ebp+8) *Curr-block-depth)
28922       (write-buffered *(ebp+8) "52/push-edx\n")
28923     }
28924     # .
28925     (emit-save-size-to *(ebp+8) %ebx "eax")
28926     (emit-indent *(ebp+8) *Curr-block-depth)
28927     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
28928     (emit-indent *(ebp+8) *Curr-block-depth)
28929     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
28930     (write-int32-hex-buffered *(ebp+8) %ecx)
28931     (write-buffered *(ebp+8) "/imm32\n")
28932     (emit-indent *(ebp+8) *Curr-block-depth)
28933     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
28934     {
28935       (string-equal? %edx "eax")  # => eax
28936       3d/compare-eax-and 0/imm32/false
28937       75/break-if-!= break/disp8
28938       (emit-indent *(ebp+8) *Curr-block-depth)
28939       (write-buffered *(ebp+8) "89/<- %")
28940       (write-buffered *(ebp+8) %edx)
28941       (write-buffered *(ebp+8) " 0/r32/eax\n")
28942     }
28943     # . emit register restores
28944     {
28945       (string-equal? %edx "edx")  # => eax
28946       3d/compare-eax-and 0/imm32/false
28947       75/break-if-!= break/disp8
28948       (emit-indent *(ebp+8) *Curr-block-depth)
28949       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
28950     }
28951     {
28952       (string-equal? %edx "ecx")  # => eax
28953       3d/compare-eax-and 0/imm32/false
28954       75/break-if-!= break/disp8
28955       (emit-indent *(ebp+8) *Curr-block-depth)
28956       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
28957     }
28958     {
28959       (string-equal? %edx "eax")  # => eax
28960       3d/compare-eax-and 0/imm32/false
28961       75/break-if-!= break/disp8
28962       (emit-indent *(ebp+8) *Curr-block-depth)
28963       (write-buffered *(ebp+8) "58/pop-to-eax\n")
28964     }
28965 $translate-mu-length-stmt:end:
28966     # . restore registers
28967     5e/pop-to-esi
28968     5b/pop-to-ebx
28969     5a/pop-to-edx
28970     59/pop-to-ecx
28971     58/pop-to-eax
28972     # . epilogue
28973     89/<- %esp 5/r32/ebp
28974     5d/pop-to-ebp
28975     c3/return
28976 
28977 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
28978     # . prologue
28979     55/push-ebp
28980     89/<- %ebp 4/r32/esp
28981     #
28982     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
28983     (size-of-type-id-as-array-element %eax)  # => eax
28984 $array-element-size:end:
28985     # . epilogue
28986     89/<- %esp 5/r32/ebp
28987     5d/pop-to-ebp
28988     c3/return
28989 
28990 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
28991     # precondition: n is positive
28992     # . prologue
28993     55/push-ebp
28994     89/<- %ebp 4/r32/esp
28995     #
28996     8b/-> *(ebp+8) 0/r32/eax
28997     # var t/eax: (addr type-tree)
28998     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
28999     # if t == 0 abort
29000     3d/compare-eax-with 0/imm32
29001     0f 84/jump-if-== $array-element-type-id:error0/disp32
29002     # if t->is-atom? abort
29003     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29004     0f 85/jump-if-!= $array-element-type-id:error1/disp32
29005     # if (t->left == addr) t = t->right
29006     {
29007       50/push-eax
29008       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29009       (simple-mu-type? %eax 2)  # addr => eax
29010       3d/compare-eax-with 0/imm32/false
29011       58/pop-to-eax
29012       74/jump-if-= break/disp8
29013 $array-element-type-id:skip-addr:
29014       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29015     }
29016     # if t == 0 abort
29017     3d/compare-eax-with 0/imm32
29018     0f 84/jump-if-= $array-element-type-id:error2/disp32
29019     # if t->is-atom? abort
29020     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29021     0f 85/jump-if-!= $array-element-type-id:error2/disp32
29022     # if t->left != array abort
29023     {
29024       50/push-eax
29025       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29026       (simple-mu-type? %eax 3)  # array => eax
29027       3d/compare-eax-with 0/imm32/false
29028       58/pop-to-eax
29029 $array-element-type-id:no-array:
29030       0f 84/jump-if-= $array-element-type-id:error2/disp32
29031     }
29032 $array-element-type-id:skip-array:
29033     # t = t->right
29034     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29035     # if t == 0 abort
29036     3d/compare-eax-with 0/imm32
29037     0f 84/jump-if-= $array-element-type-id:error2/disp32
29038     # if t->is-atom? abort
29039     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29040     0f 85/jump-if-!= $array-element-type-id:error2/disp32
29041     # t = t->left
29042     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29043     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
29044     # if (t->is-atom == false) t = lookup(t->left)
29045     {
29046       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29047       75/jump-if-!= break/disp8
29048       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29049     }
29050     # return t->value
29051     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
29052 $array-element-type-id:end:
29053     # . epilogue
29054     89/<- %esp 5/r32/ebp
29055     5d/pop-to-ebp
29056     c3/return
29057 
29058 $array-element-type-id:error0:
29059     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29060     50/push-eax
29061     8b/-> *(ebp+8) 0/r32/eax
29062     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29063     (write-buffered *(ebp+0xc) %eax)
29064     58/pop-to-eax
29065     (write-buffered *(ebp+0xc) "' has no type\n")
29066     (flush *(ebp+0xc))
29067     (stop *(ebp+0x10) 1)
29068     # never gets here
29069 
29070 $array-element-type-id:error1:
29071     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29072     50/push-eax
29073     8b/-> *(ebp+8) 0/r32/eax
29074     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29075     (write-buffered *(ebp+0xc) %eax)
29076     58/pop-to-eax
29077     (write-buffered *(ebp+0xc) "' has atomic type ")
29078     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29079     (write-buffered *(ebp+0xc) Newline)
29080     (flush *(ebp+0xc))
29081     (stop *(ebp+0x10) 1)
29082     # never gets here
29083 
29084 $array-element-type-id:error2:
29085     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
29086     50/push-eax
29087     8b/-> *(ebp+8) 0/r32/eax
29088     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29089     (write-buffered *(ebp+0xc) %eax)
29090     58/pop-to-eax
29091     (write-buffered *(ebp+0xc) "' has non-array type\n")
29092     (flush *(ebp+0xc))
29093     (stop *(ebp+0x10) 1)
29094     # never gets here
29095 
29096 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
29097     # . prologue
29098     55/push-ebp
29099     89/<- %ebp 4/r32/esp
29100     # eax = t
29101     8b/-> *(ebp+8) 0/r32/eax
29102     # if t is 'byte', size is 1
29103     3d/compare-eax-and 8/imm32/byte
29104     {
29105       75/jump-if-!= break/disp8
29106       b8/copy-to-eax 1/imm32
29107       eb/jump $size-of-type-id-as-array-element:end/disp8
29108     }
29109     # otherwise proceed as usual
29110     (size-of-type-id %eax)  # => eax
29111 $size-of-type-id-as-array-element:end:
29112     # . epilogue
29113     89/<- %esp 5/r32/ebp
29114     5d/pop-to-ebp
29115     c3/return
29116 
29117 stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
29118     # precondition: n is positive
29119     # . prologue
29120     55/push-ebp
29121     89/<- %ebp 4/r32/esp
29122     # eax = type
29123     8b/-> *(ebp+8) 0/r32/eax
29124     # if type == 0 abort
29125     3d/compare-eax-with 0/imm32
29126     0f 84/jump-if-== $stream-element-type-id:error0/disp32
29127     # if type->is-atom? abort
29128     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29129     0f 85/jump-if-!= $stream-element-type-id:error1/disp32
29130     # if (type->left == addr) type = type->right
29131     {
29132       50/push-eax
29133       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29134       (simple-mu-type? %eax 2)  # addr => eax
29135       3d/compare-eax-with 0/imm32/false
29136       58/pop-to-eax
29137       74/jump-if-= break/disp8
29138 $stream-element-type-id:skip-addr:
29139       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29140     }
29141     # if type == 0 abort
29142     3d/compare-eax-with 0/imm32
29143     0f 84/jump-if-= $stream-element-type-id:error2/disp32
29144     # if type->is-atom? abort
29145     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29146     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
29147     # if type->left != stream abort
29148     {
29149       50/push-eax
29150       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29151       (simple-mu-type? %eax 0xb)  # stream => eax
29152       3d/compare-eax-with 0/imm32/false
29153       58/pop-to-eax
29154 $stream-element-type-id:no-stream:
29155       0f 84/jump-if-= $stream-element-type-id:error2/disp32
29156     }
29157 $stream-element-type-id:skip-stream:
29158     # type = type->right
29159     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29160     # if type == 0 abort
29161     3d/compare-eax-with 0/imm32
29162     0f 84/jump-if-= $stream-element-type-id:error2/disp32
29163     # if type->is-atom? abort
29164     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29165     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
29166     # t = type->left
29167     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29168     # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
29169     {
29170       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29171       75/jump-if-!= break/disp8
29172       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29173     }
29174     # return type->value
29175     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
29176 $stream-element-type-id:end:
29177     # . epilogue
29178     89/<- %esp 5/r32/ebp
29179     5d/pop-to-ebp
29180     c3/return
29181 
29182 $stream-element-type-id:error0:
29183     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29184     50/push-eax
29185     8b/-> *(ebp+8) 0/r32/eax
29186     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29187     (write-buffered *(ebp+0xc) %eax)
29188     58/pop-to-eax
29189     (write-buffered *(ebp+0xc) "' has no type\n")
29190     (flush *(ebp+0xc))
29191     (stop *(ebp+0x10) 1)
29192     # never gets here
29193 
29194 $stream-element-type-id:error1:
29195     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29196     50/push-eax
29197     8b/-> *(ebp+8) 0/r32/eax
29198     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29199     (write-buffered *(ebp+0xc) %eax)
29200     58/pop-to-eax
29201     (write-buffered *(ebp+0xc) "' has atomic type ")
29202     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
29203     (write-buffered *(ebp+0xc) Newline)
29204     (flush *(ebp+0xc))
29205     (stop *(ebp+0x10) 1)
29206     # never gets here
29207 
29208 $stream-element-type-id:error2:
29209     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
29210     50/push-eax
29211     8b/-> *(ebp+8) 0/r32/eax
29212     (lookup *eax *(eax+4))  # Var-name Var-name => eax
29213     (write-buffered *(ebp+0xc) %eax)
29214     58/pop-to-eax
29215     (write-buffered *(ebp+0xc) "' has non-stream type\n")
29216     (flush *(ebp+0xc))
29217     (stop *(ebp+0x10) 1)
29218     # never gets here
29219 
29220 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
29221     # . prologue
29222     55/push-ebp
29223     89/<- %ebp 4/r32/esp
29224     # . save registers
29225     50/push-eax
29226     53/push-ebx
29227     # ebx = base
29228     8b/-> *(ebp+0xc) 3/r32/ebx
29229     (emit-indent *(ebp+8) *Curr-block-depth)
29230     (write-buffered *(ebp+8) "8b/-> *")
29231     # if base is an (addr array ...) in a register
29232     {
29233       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
29234       74/jump-if-= break/disp8
29235 $emit-save-size-to:emit-base-from-register:
29236       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29237       (write-buffered *(ebp+8) %eax)
29238       eb/jump $emit-save-size-to:emit-output/disp8
29239     }
29240     # otherwise if base is an (array ...) on the stack
29241     {
29242       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
29243       74/jump-if-= break/disp8
29244 $emit-save-size-to:emit-base-from-stack:
29245       (write-buffered *(ebp+8) "(ebp+")
29246       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29247       (write-buffered *(ebp+8) ")")
29248     }
29249 $emit-save-size-to:emit-output:
29250     (write-buffered *(ebp+8) " ")
29251     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
29252     (write-int32-hex-buffered *(ebp+8) *eax)
29253     (write-buffered *(ebp+8) "/r32\n")
29254 $emit-save-size-to:end:
29255     # . restore registers
29256     5b/pop-to-ebx
29257     58/pop-to-eax
29258     # . epilogue
29259     89/<- %esp 5/r32/ebp
29260     5d/pop-to-ebp
29261     c3/return
29262 
29263 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
29264     # . prologue
29265     55/push-ebp
29266     89/<- %ebp 4/r32/esp
29267     # . save registers
29268     50/push-eax
29269     #
29270     (emit-indent *(ebp+8) *Curr-block-depth)
29271     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
29272     (write-buffered *(ebp+8) *(ebp+0xc))
29273     (write-buffered *(ebp+8) Space)
29274     (num-shift-rights *(ebp+0x10))  # => eax
29275     (write-int32-hex-buffered *(ebp+8) %eax)
29276     (write-buffered *(ebp+8) "/imm8\n")
29277 $emit-divide-by-shift-right:end:
29278     # . restore registers
29279     58/pop-to-eax
29280     # . epilogue
29281     89/<- %esp 5/r32/ebp
29282     5d/pop-to-ebp
29283     c3/return
29284 
29285 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29286     # . prologue
29287     55/push-ebp
29288     89/<- %ebp 4/r32/esp
29289     # . save registers
29290     50/push-eax
29291     56/push-esi
29292     # esi = stmt
29293     8b/-> *(ebp+0xc) 6/r32/esi
29294     #
29295     (emit-indent *(ebp+8) *Curr-block-depth)
29296     (write-buffered *(ebp+8) "8a/byte->")
29297     # emit stmt->inouts[0]
29298     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29299     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29300     # emit /r32 for stmt->outputs[0]->register
29301     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29302     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29303     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29304     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
29305     (write-buffered *(ebp+8) Space)
29306     (write-int32-hex-buffered *(ebp+8) *eax)
29307     (write-buffered *(ebp+8) "/r32\n")
29308     # clear rest of register
29309     (emit-indent *(ebp+8) *Curr-block-depth)
29310     (write-buffered *(ebp+8) "81 4/subop/and %")
29311     8b/-> *(ebp+0xc) 0/r32/eax
29312     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29313     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29314     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29315     (write-buffered *(ebp+8) %eax)
29316     (write-buffered *(ebp+8) " 0xff/imm32\n")
29317 $translate-mu-copy-byte-stmt:end:
29318     # . restore registers
29319     5e/pop-to-esi
29320     58/pop-to-eax
29321     # . epilogue
29322     89/<- %esp 5/r32/ebp
29323     5d/pop-to-ebp
29324     c3/return
29325 
29326 # a little different from other translate- functions; notice the extra 'fn' argument
29327 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
29328     # . prologue
29329     55/push-ebp
29330     89/<- %ebp 4/r32/esp
29331     # . save registers
29332     53/push-ebx
29333     # ebx = stmt
29334     8b/-> *(ebp+0xc) 3/r32/ebx
29335     # var base/ebx: (addr var) = stmt->inouts[0]
29336     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29337     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29338     89/<- %ebx 0/r32/eax
29339     # emit bounds-check
29340     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
29341     # if (var->register) do one thing
29342     {
29343       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29344       74/jump-if-= break/disp8
29345       # TODO: ensure there's no dereference
29346       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29347       eb/jump $translate-mu-index-stmt:end/disp8
29348     }
29349     # if (var->offset) do a different thing
29350     {
29351       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
29352       74/jump-if-= break/disp8
29353       # TODO: ensure there's no dereference
29354       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
29355       eb/jump $translate-mu-index-stmt:end/disp8
29356     }
29357 $translate-mu-index-stmt:end:
29358     # . restore registers
29359     5b/pop-to-ebx
29360     # . epilogue
29361     89/<- %esp 5/r32/ebp
29362     5d/pop-to-ebp
29363     c3/return
29364 
29365 $translate-mu-index-stmt:error1:
29366     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
29367     (flush *(ebp+0x14))
29368     (stop *(ebp+0x18) 1)
29369     # never gets here
29370 
29371 $translate-mu-index-stmt:error2:
29372     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
29373     (flush *(ebp+0x14))
29374     (stop *(ebp+0x18) 1)
29375     # never gets here
29376 
29377 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29378     # . prologue
29379     55/push-ebp
29380     89/<- %ebp 4/r32/esp
29381     # . save registers
29382     50/push-eax
29383     51/push-ecx
29384     52/push-edx
29385     53/push-ebx
29386     # ecx = stmt
29387     8b/-> *(ebp+0xc) 1/r32/ecx
29388     #
29389     (emit-indent *(ebp+8) *Curr-block-depth)
29390     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
29391 $emit-mu-index-bounds-check:compute-base:
29392     # var base/ebx: (addr var) = inouts[0]
29393     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29394     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29395     89/<- %ebx 0/r32/eax
29396 $emit-mu-index-bounds-check:emit-index:
29397     # var index/edx: (addr var) = inouts[1]
29398     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29399     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29400     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29401     89/<- %edx 0/r32/eax
29402     # if index->register, print its code
29403     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29404     {
29405       0f 84/jump-if-= break/disp32
29406 $emit-mu-index-bounds-check:emit-register-index:
29407       (write-buffered *(ebp+8) "%")
29408       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29409       (write-buffered *(ebp+8) %eax)
29410       eb/jump $emit-mu-index-bounds-check:index-done/disp8
29411     }
29412     # otherwise if index is a literal, print it
29413 $emit-mu-index-bounds-check:emit-literal-index:
29414     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29415     (simple-mu-type? %eax 0)  # => eax
29416     3d/compare-eax-and 0/imm32/false
29417     {
29418       0f 84/jump-if-= break/disp32
29419       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29420       (write-buffered *(ebp+8) %eax)
29421     }
29422 $emit-mu-index-bounds-check:index-done:
29423     (write-buffered *(ebp+8) " ")
29424 $emit-mu-index-bounds-check:emit-element-size:
29425     # if index is a literal or int, print size of array element
29426     {
29427       {
29428         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29429         (simple-mu-type? %eax 0)  # literal => eax
29430         3d/compare-eax-and 0/imm32/false
29431         75/jump-if-!= break/disp8
29432         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29433         (simple-mu-type? %eax 1)  # int => eax
29434         3d/compare-eax-and 0/imm32/false
29435         75/jump-if-!= break/disp8
29436         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
29437       }
29438 $emit-mu-index-bounds-check:emit-int-register-index:
29439       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
29440       (write-int32-hex-buffered *(ebp+8) %eax)
29441       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
29442     }
29443 $emit-mu-index-bounds-check:emit-element-size-offset:
29444     # if index has type (offset ...), print "1"
29445     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29446     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29447     {
29448       75/jump-if-!= break/disp8
29449       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29450       (simple-mu-type? %eax 7)  # => eax
29451       3d/compare-eax-and 0/imm32/false
29452       {
29453         0f 84/jump-if-= break/disp32
29454 $emit-mu-index-bounds-check:emit-offset-register-index:
29455         (write-buffered *(ebp+8) "1")
29456       }
29457     }
29458 $emit-mu-index-bounds-check:emit-base:
29459     # if base is in a register, print " *" base->register
29460     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
29461     {
29462       74/jump-if-= break/disp8
29463       (write-buffered *(ebp+8) " *")
29464       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29465       (write-buffered *(ebp+8) %eax)
29466       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
29467     }
29468     # otherwise print " *(ebp+" base->offset ")"
29469     (write-buffered *(ebp+8) " *(ebp+")
29470     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
29471     (write-buffered *(ebp+8) ")")
29472 $emit-mu-index-bounds-check:emit-function-name:
29473     # " \"" function-name "\""
29474     (write-buffered *(ebp+8) " \"")
29475     8b/-> *(ebp+0x10) 1/r32/ecx
29476     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
29477     (write-buffered *(ebp+8) %eax)
29478     (write-buffered *(ebp+8) "\"")
29479 $emit-mu-index-bounds-check:emit-array-name:
29480     # " \"" base->name "\""
29481     (write-buffered *(ebp+8) " \"")
29482     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
29483     (write-buffered *(ebp+8) %eax)
29484     (write-buffered *(ebp+8) "\")\n")
29485 $emit-mu-index-bounds-check:end:
29486     # . restore registers
29487     5b/pop-to-ebx
29488     5a/pop-to-edx
29489     59/pop-to-ecx
29490     58/pop-to-eax
29491     # . epilogue
29492     89/<- %esp 5/r32/ebp
29493     5d/pop-to-ebp
29494     c3/return
29495 
29496 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29497     # . prologue
29498     55/push-ebp
29499     89/<- %ebp 4/r32/esp
29500     # . save registers
29501     50/push-eax
29502     51/push-ecx
29503     52/push-edx
29504     53/push-ebx
29505     # ecx = stmt
29506     8b/-> *(ebp+0xc) 1/r32/ecx
29507     # var base/ebx: (addr var) = inouts[0]
29508     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29509     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29510     89/<- %ebx 0/r32/eax
29511     # emit null check
29512     (emit-indent *(ebp+8) *Curr-block-depth)
29513     (write-buffered *(ebp+8) "81 7/subop/compare %")
29514     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29515     (write-buffered *(ebp+8) %eax)
29516     (write-buffered *(ebp+8) " 0/imm32\n")
29517     (emit-indent *(ebp+8) *Curr-block-depth)
29518     (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-index-base-address/disp32\n")
29519     #
29520     (emit-indent *(ebp+8) *Curr-block-depth)
29521     (write-buffered *(ebp+8) "8d/copy-address *(")
29522     # TODO: ensure inouts[0] is in a register and not dereferenced
29523 $translate-mu-index-stmt-with-array-in-register:emit-base:
29524     # print base->register " + "
29525     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
29526     (write-buffered *(ebp+8) %eax)
29527     (write-buffered *(ebp+8) " + ")
29528     # var index/edx: (addr var) = inouts[1]
29529     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29530     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29531     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29532     89/<- %edx 0/r32/eax
29533     # if index->register
29534     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29535     {
29536       0f 84/jump-if-= break/disp32
29537 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
29538       # if index is an int
29539       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29540       (simple-mu-type? %eax 1)  # int => eax
29541       3d/compare-eax-and 0/imm32/false
29542       {
29543         0f 84/jump-if-= break/disp32
29544 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
29545         # print index->register "<<" log2(array-element-size(base)) " + 4) "
29546         # . index->register "<<"
29547         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29548         (write-buffered *(ebp+8) %eax)
29549         (write-buffered *(ebp+8) "<<")
29550         # . log2(array-element-size(base->type))
29551         # we know size is a power of 2
29552         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29553         (num-shift-rights %eax)  # => eax
29554         (write-int32-hex-buffered *(ebp+8) %eax)
29555         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
29556       }
29557       # if index->type is any other atom, abort
29558       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29559       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29560       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29561       # if index has type (offset ...)
29562       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29563       (simple-mu-type? %eax 7)  # => eax
29564       3d/compare-eax-and 0/imm32/false
29565       {
29566         0f 84/jump-if-= break/disp32
29567         # print index->register
29568 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
29569         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29570         (write-buffered *(ebp+8) %eax)
29571       }
29572 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
29573       (write-buffered *(ebp+8) " + 4) ")
29574       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29575     }
29576     # otherwise if index is a literal
29577     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29578     (simple-mu-type? %eax 0)  # => eax
29579     3d/compare-eax-and 0/imm32/false
29580     {
29581       0f 84/jump-if-= break/disp32
29582 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
29583       # var index-value/edx: int = parse-hex-int(index->name)
29584       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29585       (parse-hex-int %eax)  # => eax
29586       89/<- %edx 0/r32/eax
29587       # offset = idx-value * array-element-size(base->type)
29588       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29589       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29590       # offset += 4 for array size
29591       05/add-to-eax 4/imm32
29592       # TODO: check edx for overflow
29593       # print offset
29594       (write-int32-hex-buffered *(ebp+8) %eax)
29595       (write-buffered *(ebp+8) ") ")
29596       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
29597     }
29598     # otherwise abort
29599     e9/jump $translate-mu-index-stmt:error1/disp32
29600 $translate-mu-index-stmt-with-array-in-register:emit-output:
29601     # outputs[0] "/r32"
29602     8b/-> *(ebp+0xc) 1/r32/ecx
29603     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29604     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29605     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29606     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29607     (write-int32-hex-buffered *(ebp+8) *eax)
29608     (write-buffered *(ebp+8) "/r32\n")
29609 $translate-mu-index-stmt-with-array-in-register:end:
29610     # . restore registers
29611     5b/pop-to-ebx
29612     5a/pop-to-edx
29613     59/pop-to-ecx
29614     58/pop-to-eax
29615     # . epilogue
29616     89/<- %esp 5/r32/ebp
29617     5d/pop-to-ebp
29618     c3/return
29619 
29620 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29621     # . prologue
29622     55/push-ebp
29623     89/<- %ebp 4/r32/esp
29624     # . save registers
29625     50/push-eax
29626     51/push-ecx
29627     52/push-edx
29628     53/push-ebx
29629     #
29630     (emit-indent *(ebp+8) *Curr-block-depth)
29631     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
29632     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
29633     8b/-> *(ebp+0xc) 0/r32/eax
29634     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29635     89/<- %edx 0/r32/eax
29636     # var base/ecx: (addr var) = lookup(curr->value)
29637     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29638     89/<- %ecx 0/r32/eax
29639     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
29640     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
29641     # var index/edx: (handle var) = curr2->value
29642     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29643     89/<- %edx 0/r32/eax
29644     # if index->register
29645     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
29646     {
29647       0f 84/jump-if-= break/disp32
29648 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
29649       # if index is an int
29650       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29651       (simple-mu-type? %eax 1)  # int => eax
29652       3d/compare-eax-and 0/imm32/false
29653       {
29654         0f 84/jump-if-= break/disp32
29655 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
29656         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
29657         # . inouts[1]->register "<<"
29658         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29659         (write-buffered *(ebp+8) %eax)
29660         (write-buffered *(ebp+8) "<<")
29661         # . log2(array-element-size(base))
29662         # TODO: ensure size is a power of 2
29663         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29664         (num-shift-rights %eax)  # => eax
29665         (write-int32-hex-buffered *(ebp+8) %eax)
29666         #
29667         (write-buffered *(ebp+8) " + ")
29668         #
29669         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
29670         05/add-to-eax 4/imm32  # for array length
29671         (write-int32-hex-buffered *(ebp+8) %eax)
29672         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
29673       }
29674       # if index->type is any other atom, abort
29675       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29676       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
29677       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
29678       # if index has type (offset ...)
29679       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29680       (simple-mu-type? %eax 7)  # => eax
29681       3d/compare-eax-and 0/imm32/false
29682       {
29683         0f 84/jump-if-= break/disp32
29684         # print index->register
29685 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
29686         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
29687         (write-buffered *(ebp+8) %eax)
29688       }
29689 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
29690       (write-buffered *(ebp+8) ") ")
29691       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29692     }
29693     # otherwise if index is a literal
29694     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
29695     (simple-mu-type? %eax 0)  # => eax
29696     3d/compare-eax-and 0/imm32/false
29697     {
29698       0f 84/jump-if-= break/disp32
29699 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
29700       # var idx-value/edx: int = parse-hex-int(index->name)
29701       (lookup *edx *(edx+4))  # Var-name Var-name => eax
29702       (parse-hex-int %eax)  # Var-name => eax
29703       89/<- %edx 0/r32/eax
29704       # offset = idx-value * array-element-size(base)
29705       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
29706       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
29707       # offset += base->offset
29708       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
29709       # offset += 4 for array size
29710       05/add-to-eax 4/imm32
29711       # TODO: check edx for overflow
29712       # print offset
29713       (write-int32-hex-buffered *(ebp+8) %eax)
29714       (write-buffered *(ebp+8) ") ")
29715       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
29716     }
29717     # otherwise abort
29718     e9/jump $translate-mu-index-stmt:error1/disp32
29719 $translate-mu-index-stmt-with-array-on-stack:emit-output:
29720     # outputs[0] "/r32"
29721     8b/-> *(ebp+0xc) 0/r32/eax
29722     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29723     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29724     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29725     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29726     (write-int32-hex-buffered *(ebp+8) *eax)
29727     (write-buffered *(ebp+8) "/r32\n")
29728 $translate-mu-index-stmt-with-array-on-stack:end:
29729     # . restore registers
29730     5b/pop-to-ebx
29731     5a/pop-to-edx
29732     59/pop-to-ecx
29733     58/pop-to-eax
29734     # . epilogue
29735     89/<- %esp 5/r32/ebp
29736     5d/pop-to-ebp
29737     c3/return
29738 
29739 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29740     # . prologue
29741     55/push-ebp
29742     89/<- %ebp 4/r32/esp
29743     # . save registers
29744     50/push-eax
29745     51/push-ecx
29746     52/push-edx
29747     53/push-ebx
29748     #
29749     (emit-indent *(ebp+8) *Curr-block-depth)
29750     (write-buffered *(ebp+8) "69/multiply")
29751     # ecx = stmt
29752     8b/-> *(ebp+0xc) 1/r32/ecx
29753     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
29754     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29755     89/<- %ebx 0/r32/eax
29756 $translate-mu-compute-index-stmt:emit-index:
29757     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
29758     (emit-subx-var-as-rm32 *(ebp+8) %eax)
29759     (write-buffered *(ebp+8) Space)
29760 $translate-mu-compute-index-stmt:emit-elem-size:
29761     # var base/ebx: (addr var)
29762     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
29763     89/<- %ebx 0/r32/eax
29764     # print array-element-size(base)
29765     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
29766     (write-int32-hex-buffered *(ebp+8) %eax)
29767     (write-buffered *(ebp+8) "/imm32 ")
29768 $translate-mu-compute-index-stmt:emit-output:
29769     # outputs[0] "/r32"
29770     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29771     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29772     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29773     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29774     (write-int32-hex-buffered *(ebp+8) *eax)
29775     (write-buffered *(ebp+8) "/r32\n")
29776 $translate-mu-compute-index-stmt:end:
29777     # . restore registers
29778     5b/pop-to-ebx
29779     5a/pop-to-edx
29780     59/pop-to-ecx
29781     58/pop-to-eax
29782     # . epilogue
29783     89/<- %esp 5/r32/ebp
29784     5d/pop-to-ebp
29785     c3/return
29786 
29787 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
29788     # . prologue
29789     55/push-ebp
29790     89/<- %ebp 4/r32/esp
29791     # . save registers
29792     50/push-eax
29793     51/push-ecx
29794     52/push-edx
29795     # ecx = stmt
29796     8b/-> *(ebp+0xc) 1/r32/ecx
29797     # var base/eax: (addr var) = stmt->inouts->value
29798     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29799     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29800     # if base is in a register, insert a null check
29801     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29802     {
29803       0f 84/jump-if-= break/disp32
29804 $translate-mu-get-stmt:emit-null-check-for-register-input:
29805       # emit "81 7/subop/compare %" base->register " 0/imm32\n"
29806       (emit-indent *(ebp+8) *Curr-block-depth)
29807       (write-buffered *(ebp+8) "81 7/subop/compare %")
29808       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29809       (write-buffered *(ebp+8) %eax)
29810       (write-buffered *(ebp+8) " 0/imm32\n")
29811       #
29812       (emit-indent *(ebp+8) *Curr-block-depth)
29813       (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32\n")
29814     }
29815     # var offset/edx: int = get offset of stmt
29816     (mu-get-offset %ecx)  # => eax
29817     89/<- %edx 0/r32/eax
29818     # var base/eax: (addr var) = stmt->inouts->value
29819     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29820     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29821     #
29822     (emit-indent *(ebp+8) *Curr-block-depth)
29823     (write-buffered *(ebp+8) "8d/copy-address ")
29824     # if base is in a register
29825     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
29826     {
29827       0f 84/jump-if-= break/disp32
29828 $translate-mu-get-stmt:emit-register-input:
29829       # emit "*(" base->register " + " offset ") "
29830       (write-buffered *(ebp+8) "*(")
29831       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29832       (write-buffered *(ebp+8) %eax)
29833       (write-buffered *(ebp+8) " + ")
29834       (write-int32-hex-buffered *(ebp+8) %edx)
29835       (write-buffered *(ebp+8) ") ")
29836       e9/jump $translate-mu-get-stmt:emit-output/disp32
29837     }
29838     # otherwise base is on the stack
29839     {
29840 $translate-mu-get-stmt:emit-stack-input:
29841       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
29842       (write-buffered *(ebp+8) "*(ebp+")
29843       03/add *(eax+0x14) 2/r32/edx  # Var-offset
29844       (write-int32-hex-buffered *(ebp+8) %edx)
29845       (write-buffered *(ebp+8) ") ")
29846       eb/jump $translate-mu-get-stmt:emit-output/disp8
29847     }
29848 $translate-mu-get-stmt:emit-output:
29849     # var output/eax: (addr var) = stmt->outputs->value
29850     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
29851     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29852     # emit offset->register "/r32"
29853     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
29854     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
29855     (write-int32-hex-buffered *(ebp+8) *eax)
29856     (write-buffered *(ebp+8) "/r32\n")
29857 $translate-mu-get-stmt:end:
29858     # . restore registers
29859     5a/pop-to-edx
29860     59/pop-to-ecx
29861     58/pop-to-eax
29862     # . epilogue
29863     89/<- %esp 5/r32/ebp
29864     5d/pop-to-ebp
29865     c3/return
29866 
29867 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29868     # . prologue
29869     55/push-ebp
29870     89/<- %ebp 4/r32/esp
29871     # . save registers
29872     50/push-eax
29873     #
29874     (emit-indent *(ebp+8) *Curr-block-depth)
29875     (write-buffered *(ebp+8) "(copy-bytes")
29876     # eax = stmt
29877     8b/-> *(ebp+0xc) 0/r32/eax
29878     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
29879     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29880     (emit-subx-call-operand *(ebp+8) %eax)
29881     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
29882     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
29883     (emit-subx-call-operand *(ebp+8) %eax)
29884     # emit size of inouts
29885     (write-buffered *(ebp+8) Space)
29886     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29887     (write-int32-hex-buffered *(ebp+8) %eax)
29888     (write-buffered *(ebp+8) ")\n")
29889 $translate-mu-copy-object-stmt:end:
29890     # . restore registers
29891     58/pop-to-eax
29892     # . epilogue
29893     89/<- %esp 5/r32/ebp
29894     5d/pop-to-ebp
29895     c3/return
29896 
29897 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29898     # . prologue
29899     55/push-ebp
29900     89/<- %ebp 4/r32/esp
29901     # . save registers
29902     50/push-eax
29903     #
29904     (emit-indent *(ebp+8) *Curr-block-depth)
29905     (write-buffered *(ebp+8) "(zero-out")
29906     # eax = stmt
29907     8b/-> *(ebp+0xc) 0/r32/eax
29908     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
29909     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29910     #
29911     (emit-subx-call-operand *(ebp+8) %eax)
29912     (write-buffered *(ebp+8) Space)
29913     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
29914     (write-int32-hex-buffered *(ebp+8) %eax)
29915     (write-buffered *(ebp+8) ")\n")
29916 $translate-mu-clear-object-stmt:end:
29917     # . restore registers
29918     58/pop-to-eax
29919     # . epilogue
29920     89/<- %esp 5/r32/ebp
29921     5d/pop-to-ebp
29922     c3/return
29923 
29924 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
29925     # . prologue
29926     55/push-ebp
29927     89/<- %ebp 4/r32/esp
29928     # . save registers
29929     50/push-eax
29930     56/push-esi
29931     57/push-edi
29932     # esi = stmt
29933     8b/-> *(ebp+0xc) 6/r32/esi
29934     # var target/edi: (addr stmt-var) = stmt->inouts[0]
29935     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
29936     89/<- %edi 0/r32/eax
29937     #
29938     (emit-indent *(ebp+8) *Curr-block-depth)
29939     (write-buffered *(ebp+8) "(allocate Heap ")
29940     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
29941     (write-int32-hex-buffered *(ebp+8) %eax)
29942     (emit-subx-call-operand *(ebp+8) %edi)
29943     (write-buffered *(ebp+8) ")\n")
29944 $translate-mu-allocate-stmt:end:
29945     # . restore registers
29946     5f/pop-to-edi
29947     5e/pop-to-esi
29948     58/pop-to-eax
29949     # . epilogue
29950     89/<- %esp 5/r32/ebp
29951     5d/pop-to-ebp
29952     c3/return
29953 
29954 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29955     # . prologue
29956     55/push-ebp
29957     89/<- %ebp 4/r32/esp
29958     # var t/eax: (addr type-tree) = s->value->type
29959     8b/-> *(ebp+8) 0/r32/eax
29960     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29961     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29962     # TODO: check eax != 0
29963     # TODO: check !t->is-atom?
29964     # TODO: check t->left == addr
29965     # t = t->right
29966 $addr-handle-payload-size:skip-addr:
29967     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29968     # TODO: check eax != 0
29969     # TODO: check !t->is-atom?
29970     # TODO: check t->left == handle
29971     # t = t->right
29972 $addr-handle-payload-size:skip-handle:
29973     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
29974     # TODO: check eax != 0
29975     # if !t->is-atom? t = t->left
29976     81 7/subop/compare *eax 0/imm32/false
29977     {
29978       75/jump-if-!= break/disp8
29979       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
29980     }
29981     # TODO: check t->is-atom?
29982     # return size(t->value)
29983     (size-of-type-id *(eax+4))  # Type-tree-value => eax
29984 $addr-handle-payload-size:end:
29985     # . epilogue
29986     89/<- %esp 5/r32/ebp
29987     5d/pop-to-ebp
29988     c3/return
29989 
29990 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
29991     # . prologue
29992     55/push-ebp
29993     89/<- %ebp 4/r32/esp
29994     # var t/eax: (addr type-tree) = s->value->type
29995     8b/-> *(ebp+8) 0/r32/eax
29996     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
29997     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
29998     # TODO: check eax != 0
29999     # TODO: check !t->is-atom?
30000     # TODO: check t->left == addr
30001     # t = t->right
30002 $addr-payload-size:skip-addr:
30003     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30004     # TODO: check eax != 0
30005     # if !t->is-atom? t = t->left
30006     81 7/subop/compare *eax 0/imm32/false
30007     {
30008       75/jump-if-!= break/disp8
30009       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30010     }
30011     # TODO: check t->is-atom?
30012     # return size(t->value)
30013     (size-of-type-id *(eax+4))  # Type-tree-value => eax
30014 $addr-payload-size:end:
30015     # . epilogue
30016     89/<- %esp 5/r32/ebp
30017     5d/pop-to-ebp
30018     c3/return
30019 
30020 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30021     # . prologue
30022     55/push-ebp
30023     89/<- %ebp 4/r32/esp
30024     # . save registers
30025     50/push-eax
30026     51/push-ecx
30027     56/push-esi
30028     57/push-edi
30029     # esi = stmt
30030     8b/-> *(ebp+0xc) 6/r32/esi
30031     # var target/edi: (addr stmt-var) = stmt->inouts[0]
30032     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30033     89/<- %edi 0/r32/eax
30034     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
30035     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
30036     89/<- %ecx 0/r32/eax
30037     #
30038     (emit-indent *(ebp+8) *Curr-block-depth)
30039     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
30040     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30041     (write-int32-hex-buffered *(ebp+8) %eax)
30042     (emit-subx-call-operand *(ebp+8) %ecx)
30043     (emit-subx-call-operand *(ebp+8) %edi)
30044     (write-buffered *(ebp+8) ")\n")
30045 $translate-mu-populate-stmt:end:
30046     # . restore registers
30047     5f/pop-to-edi
30048     5e/pop-to-esi
30049     59/pop-to-ecx
30050     58/pop-to-eax
30051     # . epilogue
30052     89/<- %esp 5/r32/ebp
30053     5d/pop-to-ebp
30054     c3/return
30055 
30056 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30057     # . prologue
30058     55/push-ebp
30059     89/<- %ebp 4/r32/esp
30060     # . save registers
30061     50/push-eax
30062     51/push-ecx
30063     56/push-esi
30064     57/push-edi
30065     # esi = stmt
30066     8b/-> *(ebp+0xc) 6/r32/esi
30067     # var target/edi: (addr stmt-var) = stmt->inouts[0]
30068     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30069     89/<- %edi 0/r32/eax
30070     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
30071     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
30072     89/<- %ecx 0/r32/eax
30073     #
30074     (emit-indent *(ebp+8) *Curr-block-depth)
30075     (write-buffered *(ebp+8) "(new-stream Heap ")
30076     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30077     (write-int32-hex-buffered *(ebp+8) %eax)
30078     (emit-subx-call-operand *(ebp+8) %ecx)
30079     (emit-subx-call-operand *(ebp+8) %edi)
30080     (write-buffered *(ebp+8) ")\n")
30081 $translate-mu-populate-stream-stmt:end:
30082     # . restore registers
30083     5f/pop-to-edi
30084     5e/pop-to-esi
30085     59/pop-to-ecx
30086     58/pop-to-eax
30087     # . epilogue
30088     89/<- %esp 5/r32/ebp
30089     5d/pop-to-ebp
30090     c3/return
30091 
30092 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30093     # . prologue
30094     55/push-ebp
30095     89/<- %ebp 4/r32/esp
30096     # . save registers
30097     50/push-eax
30098     51/push-ecx
30099     56/push-esi
30100     57/push-edi
30101     # esi = stmt
30102     8b/-> *(ebp+0xc) 6/r32/esi
30103     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
30104     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30105     89/<- %ecx 0/r32/eax
30106     # var target/edi: (addr stmt-var) = stmt->inouts[1]
30107     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
30108     89/<- %edi 0/r32/eax
30109     #
30110     (emit-indent *(ebp+8) *Curr-block-depth)
30111     (write-buffered *(ebp+8) "(read-from-stream")
30112     (emit-subx-call-operand *(ebp+8) %ecx)
30113     (emit-subx-call-operand *(ebp+8) %edi)
30114     (write-buffered *(ebp+8) Space)
30115     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30116     (write-int32-hex-buffered *(ebp+8) %eax)
30117     (write-buffered *(ebp+8) ")\n")
30118 $translate-mu-read-from-stream-stmt:end:
30119     # . restore registers
30120     5f/pop-to-edi
30121     5e/pop-to-esi
30122     59/pop-to-ecx
30123     58/pop-to-eax
30124     # . epilogue
30125     89/<- %esp 5/r32/ebp
30126     5d/pop-to-ebp
30127     c3/return
30128 
30129 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
30130     # . prologue
30131     55/push-ebp
30132     89/<- %ebp 4/r32/esp
30133     # . save registers
30134     50/push-eax
30135     51/push-ecx
30136     56/push-esi
30137     57/push-edi
30138     # esi = stmt
30139     8b/-> *(ebp+0xc) 6/r32/esi
30140     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
30141     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30142     89/<- %ecx 0/r32/eax
30143     # var target/edi: (addr stmt-var) = stmt->inouts[1]
30144     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
30145     89/<- %edi 0/r32/eax
30146     #
30147     (emit-indent *(ebp+8) *Curr-block-depth)
30148     (write-buffered *(ebp+8) "(write-to-stream")
30149     (emit-subx-call-operand *(ebp+8) %ecx)
30150     (flush *(ebp+8))
30151     (emit-subx-call-operand *(ebp+8) %edi)
30152     (flush *(ebp+8))
30153     (write-buffered *(ebp+8) Space)
30154     (flush *(ebp+8))
30155     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
30156     (write-int32-hex-buffered *(ebp+8) %eax)
30157     (write-buffered *(ebp+8) ")\n")
30158 $translate-mu-write-to-stream-stmt:end:
30159     # . restore registers
30160     5f/pop-to-edi
30161     5e/pop-to-esi
30162     59/pop-to-ecx
30163     58/pop-to-eax
30164     # . epilogue
30165     89/<- %esp 5/r32/ebp
30166     5d/pop-to-ebp
30167     c3/return
30168 
30169 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30170     # . prologue
30171     55/push-ebp
30172     89/<- %ebp 4/r32/esp
30173     # var t/eax: (addr type-tree) = s->value->type
30174     8b/-> *(ebp+8) 0/r32/eax
30175     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30176     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30177     # TODO: check eax != 0
30178     # TODO: check !t->is-atom?
30179     # TODO: check t->left == addr
30180     # t = t->right
30181 $addr-handle-array-payload-size:skip-addr:
30182     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30183     # TODO: check eax != 0
30184     # TODO: check !t->is-atom?
30185     # TODO: check t->left == handle
30186     # t = t->right
30187 $addr-handle-array-payload-size:skip-handle:
30188     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30189     # TODO: check eax != 0
30190     # TODO: check !t->is-atom?
30191     # TODO: check t->left == array
30192     # t = t->right
30193 $addr-handle-array-payload-size:skip-array:
30194     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30195     # TODO: check eax != 0
30196     # if !t->is-atom? t = t->left
30197     81 7/subop/compare *eax 0/imm32/false
30198     {
30199       75/jump-if-!= break/disp8
30200       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30201     }
30202 $addr-handle-array-payload-size:compute-size:
30203     # TODO: check t->is-atom?
30204     # return size(t->value)
30205     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30206 $addr-handle-array-payload-size:end:
30207     # . epilogue
30208     89/<- %esp 5/r32/ebp
30209     5d/pop-to-ebp
30210     c3/return
30211 
30212 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
30213     # . prologue
30214     55/push-ebp
30215     89/<- %ebp 4/r32/esp
30216     # var t/eax: (addr type-tree) = s->value->type
30217     8b/-> *(ebp+8) 0/r32/eax
30218     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30219     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
30220     # TODO: check eax != 0
30221     # TODO: check !t->is-atom?
30222     # TODO: check t->left == addr
30223     # t = t->right
30224 $addr-handle-stream-payload-size:skip-addr:
30225     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30226     # TODO: check eax != 0
30227     # TODO: check !t->is-atom?
30228     # TODO: check t->left == handle
30229     # t = t->right
30230 $addr-handle-stream-payload-size:skip-handle:
30231     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30232     # TODO: check eax != 0
30233     # TODO: check !t->is-atom?
30234     # TODO: check t->left == stream
30235     # t = t->right
30236 $addr-handle-stream-payload-size:skip-stream:
30237     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
30238     # TODO: check eax != 0
30239     # if !t->is-atom? t = t->left
30240     81 7/subop/compare *eax 0/imm32/false
30241     {
30242       75/jump-if-!= break/disp8
30243       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
30244     }
30245 $addr-handle-stream-payload-size:compute-size:
30246     # TODO: check t->is-atom?
30247     # return size(t->value)
30248     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
30249 $addr-handle-stream-payload-size:end:
30250     # . epilogue
30251     89/<- %esp 5/r32/ebp
30252     5d/pop-to-ebp
30253     c3/return
30254 
30255 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
30256     # precondition: n is positive
30257     # . prologue
30258     55/push-ebp
30259     89/<- %ebp 4/r32/esp
30260     # eax = n
30261     8b/-> *(ebp+8) 0/r32/eax
30262     # if (n < 0) abort
30263     3d/compare-eax-with 0/imm32
30264     0f 8c/jump-if-< $power-of-2?:abort/disp32
30265     # var tmp/eax: int = n-1
30266     48/decrement-eax
30267     # var tmp2/eax: int = n & tmp
30268     23/and-> *(ebp+8) 0/r32/eax
30269     # return (tmp2 == 0)
30270     3d/compare-eax-and 0/imm32
30271     0f 94/set-byte-if-= %al
30272     25/and-eax-with 0xff/imm32
30273 $power-of-2?:end:
30274     # . epilogue
30275     89/<- %esp 5/r32/ebp
30276     5d/pop-to-ebp
30277     c3/return
30278 
30279 $power-of-2?:abort:
30280     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
30281     (flush *(ebp+0xc))
30282     (stop *(ebp+0x10) 1)
30283     # never gets here
30284 
30285 num-shift-rights:  # n: int -> result/eax: int
30286     # precondition: n is a positive power of 2
30287     # . prologue
30288     55/push-ebp
30289     89/<- %ebp 4/r32/esp
30290     # . save registers
30291     51/push-ecx
30292     # var curr/ecx: int = n
30293     8b/-> *(ebp+8) 1/r32/ecx
30294     # result = 0
30295     b8/copy-to-eax 0/imm32
30296     {
30297       # if (curr <= 1) break
30298       81 7/subop/compare %ecx 1/imm32
30299       7e/jump-if-<= break/disp8
30300       40/increment-eax
30301       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
30302       eb/jump loop/disp8
30303     }
30304 $num-shift-rights:end:
30305     # . restore registers
30306     59/pop-to-ecx
30307     # . epilogue
30308     89/<- %esp 5/r32/ebp
30309     5d/pop-to-ebp
30310     c3/return
30311 
30312 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
30313     # . prologue
30314     55/push-ebp
30315     89/<- %ebp 4/r32/esp
30316     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
30317     8b/-> *(ebp+8) 0/r32/eax
30318     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
30319     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
30320     # var output-var/eax: (addr var) = second-inout->value
30321     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
30322 #?     (write-buffered Stderr "mu-get-offset: ")
30323 #?     (write-int32-hex-buffered Stderr %eax)
30324 #?     (write-buffered Stderr " name: ")
30325 #?     50/push-eax
30326 #?     (lookup *eax *(eax+4))  # Var-name
30327 #?     (write-buffered Stderr %eax)
30328 #?     58/pop-to-eax
30329 #?     (write-buffered Stderr Newline)
30330 #?     (flush Stderr)
30331     # return output-var->stack-offset
30332     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
30333 #?     (write-buffered Stderr "=> ")
30334 #?     (write-int32-hex-buffered Stderr %eax)
30335 #?     (write-buffered Stderr Newline)
30336 #?     (flush Stderr)
30337 $emit-get-offset:end:
30338     # . epilogue
30339     89/<- %esp 5/r32/ebp
30340     5d/pop-to-ebp
30341     c3/return
30342 
30343 emit-subx-block:  # out: (addr buffered-file), block: (addr block), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
30344     # . prologue
30345     55/push-ebp
30346     89/<- %ebp 4/r32/esp
30347     # . save registers
30348     50/push-eax
30349     51/push-ecx
30350     56/push-esi
30351     # esi = block
30352     8b/-> *(ebp+0xc) 6/r32/esi
30353     # block->var->block-depth = *Curr-block-depth
30354     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30355     8b/-> *Curr-block-depth 1/r32/ecx
30356     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
30357     # var stmts/eax: (addr list stmt) = lookup(block->statements)
30358     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30359     #
30360     {
30361 $emit-subx-block:check-empty:
30362       3d/compare-eax-and 0/imm32
30363       0f 84/jump-if-= break/disp32
30364       (emit-indent *(ebp+8) *Curr-block-depth)
30365       (write-buffered *(ebp+8) "{\n")
30366       # var v/ecx: (addr var) = lookup(block->var)
30367       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
30368       89/<- %ecx 0/r32/eax
30369       #
30370       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30371       (write-buffered *(ebp+8) %eax)
30372       (write-buffered *(ebp+8) ":loop:\n")
30373       ff 0/subop/increment *Curr-block-depth
30374       (push *(ebp+0x10) *(esi+0xc))  # Block-var
30375       (push *(ebp+0x10) *(esi+0x10))  # Block-var
30376       (push *(ebp+0x10) 0)  # false
30377       # emit block->statements
30378       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
30379       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
30380       (pop *(ebp+0x10))  # => eax
30381       (pop *(ebp+0x10))  # => eax
30382       (pop *(ebp+0x10))  # => eax
30383       ff 1/subop/decrement *Curr-block-depth
30384       (emit-indent *(ebp+8) *Curr-block-depth)
30385       (write-buffered *(ebp+8) "}\n")
30386       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
30387       (write-buffered *(ebp+8) %eax)
30388       (write-buffered *(ebp+8) ":break:\n")
30389     }
30390 $emit-subx-block:end:
30391     # . restore registers
30392     5e/pop-to-esi
30393     59/pop-to-ecx
30394     58/pop-to-eax
30395     # . epilogue
30396     89/<- %esp 5/r32/ebp
30397     5d/pop-to-ebp
30398     c3/return
30399 
30400 # Primitives supported
30401 # See mu_instructions for a summary of this linked-list data structure.
30402 #
30403 # For each operation, put variants with hard-coded registers before flexible ones.
30404 #
30405 # Unfortunately, our restrictions on addresses require that various fields in
30406 # primitives be handles, which complicates these definitions.
30407 #   - we need to insert dummy fields all over the place for fake alloc-ids
30408 #   - we can't use our syntax sugar of quoted literals for string fields
30409 #
30410 # Fake alloc-ids are needed because our type definitions up top require
30411 # handles but it's clearer to statically allocate these long-lived objects.
30412 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
30413 #
30414 # Every 'object' below starts with a fake alloc-id. It may also contain other
30415 # fake alloc-ids for various handle fields.
30416 #
30417 # I think of objects starting with a fake alloc-id as having type 'payload'.
30418 # It's not really intended to be created dynamically; for that use `allocate`
30419 # as usual.
30420 #
30421 # Idea for a notation to simplify such definitions:
30422 #   _Primitive-increment-eax:  # (payload primitive)
30423 #     0x11/alloc-id:fake:payload
30424 #     0x11 @(0x11 "increment")  # name
30425 #     0 0                       # inouts
30426 #     0x11 @(0x11/payload
30427 #            0x11 @(0x11/payload  # List-value
30428 #                   0 0             # Var-name
30429 #                   0x11 @(0x11     # Var-type
30430 #                          1/is-atom
30431 #                          1/value 0/unused   # Type-tree-left
30432 #                          0 0                # Type-tree-right
30433 #                         )
30434 #                   1               # block-depth
30435 #                   0               # stack-offset
30436 #                   0x11 @(0x11 "eax")  # Var-register
30437 #                  )
30438 #            0 0)                 # List-next
30439 #     ...
30440 #     _Primitive-increment-ecx/imm32/next
30441 #   ...
30442 # Awfully complex and non-obvious. But also clearly signals there's something
30443 # to learn here, so may be worth trying.
30444 #
30445 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
30446 #
30447 # For now we'll continue to just use comments and manually ensure they stay up
30448 # to date.
30449 == data
30450 Primitives:  # (addr primitive)
30451 # - increment/decrement
30452 _Primitive-increment-eax:  # (addr primitive)
30453     # var/eax <- increment => 40/increment-eax
30454     0x11/imm32/alloc-id:fake
30455     _string-increment/imm32/name
30456     0/imm32/no-inouts
30457     0/imm32/no-inouts
30458     0x11/imm32/alloc-id:fake
30459     Single-int-var-in-eax/imm32/outputs
30460     0x11/imm32/alloc-id:fake
30461     _string_40_increment_eax/imm32/subx-name
30462     0/imm32/no-rm32
30463     0/imm32/no-r32
30464     0/imm32/no-imm32
30465     0/imm32/no-imm8
30466     0/imm32/no-disp32
30467     0/imm32/no-xm32
30468     0/imm32/no-x32
30469     0x11/imm32/alloc-id:fake
30470     _Primitive-increment-ecx/imm32/next
30471 _Primitive-increment-ecx:  # (payload primitive)
30472     0x11/imm32/alloc-id:fake:payload
30473     # var/ecx <- increment => 41/increment-ecx
30474     0x11/imm32/alloc-id:fake
30475     _string-increment/imm32/name
30476     0/imm32/no-inouts
30477     0/imm32/no-inouts
30478     0x11/imm32/alloc-id:fake
30479     Single-int-var-in-ecx/imm32/outputs
30480     0x11/imm32/alloc-id:fake
30481     _string_41_increment_ecx/imm32/subx-name
30482     0/imm32/no-rm32
30483     0/imm32/no-r32
30484     0/imm32/no-imm32
30485     0/imm32/no-imm8
30486     0/imm32/no-disp32
30487     0/imm32/no-xm32
30488     0/imm32/no-x32
30489     0x11/imm32/alloc-id:fake
30490     _Primitive-increment-edx/imm32/next
30491 _Primitive-increment-edx:  # (payload primitive)
30492     0x11/imm32/alloc-id:fake:payload
30493     # var/edx <- increment => 42/increment-edx
30494     0x11/imm32/alloc-id:fake
30495     _string-increment/imm32/name
30496     0/imm32/no-inouts
30497     0/imm32/no-inouts
30498     0x11/imm32/alloc-id:fake
30499     Single-int-var-in-edx/imm32/outputs
30500     0x11/imm32/alloc-id:fake
30501     _string_42_increment_edx/imm32/subx-name
30502     0/imm32/no-rm32
30503     0/imm32/no-r32
30504     0/imm32/no-imm32
30505     0/imm32/no-imm8
30506     0/imm32/no-disp32
30507     0/imm32/no-xm32
30508     0/imm32/no-x32
30509     0x11/imm32/alloc-id:fake
30510     _Primitive-increment-ebx/imm32/next
30511 _Primitive-increment-ebx:  # (payload primitive)
30512     0x11/imm32/alloc-id:fake:payload
30513     # var/ebx <- increment => 43/increment-ebx
30514     0x11/imm32/alloc-id:fake
30515     _string-increment/imm32/name
30516     0/imm32/no-inouts
30517     0/imm32/no-inouts
30518     0x11/imm32/alloc-id:fake
30519     Single-int-var-in-ebx/imm32/outputs
30520     0x11/imm32/alloc-id:fake
30521     _string_43_increment_ebx/imm32/subx-name
30522     0/imm32/no-rm32
30523     0/imm32/no-r32
30524     0/imm32/no-imm32
30525     0/imm32/no-imm8
30526     0/imm32/no-disp32
30527     0/imm32/no-xm32
30528     0/imm32/no-x32
30529     0x11/imm32/alloc-id:fake
30530     _Primitive-increment-esi/imm32/next
30531 _Primitive-increment-esi:  # (payload primitive)
30532     0x11/imm32/alloc-id:fake:payload
30533     # var/esi <- increment => 46/increment-esi
30534     0x11/imm32/alloc-id:fake
30535     _string-increment/imm32/name
30536     0/imm32/no-inouts
30537     0/imm32/no-inouts
30538     0x11/imm32/alloc-id:fake
30539     Single-int-var-in-esi/imm32/outputs
30540     0x11/imm32/alloc-id:fake
30541     _string_46_increment_esi/imm32/subx-name
30542     0/imm32/no-rm32
30543     0/imm32/no-r32
30544     0/imm32/no-imm32
30545     0/imm32/no-imm8
30546     0/imm32/no-disp32
30547     0/imm32/no-xm32
30548     0/imm32/no-x32
30549     0x11/imm32/alloc-id:fake
30550     _Primitive-increment-edi/imm32/next
30551 _Primitive-increment-edi:  # (payload primitive)
30552     0x11/imm32/alloc-id:fake:payload
30553     # var/edi <- increment => 47/increment-edi
30554     0x11/imm32/alloc-id:fake
30555     _string-increment/imm32/name
30556     0/imm32/no-inouts
30557     0/imm32/no-inouts
30558     0x11/imm32/alloc-id:fake
30559     Single-int-var-in-edi/imm32/outputs
30560     0x11/imm32/alloc-id:fake
30561     _string_47_increment_edi/imm32/subx-name
30562     0/imm32/no-rm32
30563     0/imm32/no-r32
30564     0/imm32/no-imm32
30565     0/imm32/no-imm8
30566     0/imm32/no-disp32
30567     0/imm32/no-xm32
30568     0/imm32/no-x32
30569     0x11/imm32/alloc-id:fake
30570     _Primitive-decrement-eax/imm32/next
30571 _Primitive-decrement-eax:  # (payload primitive)
30572     0x11/imm32/alloc-id:fake:payload
30573     # var/eax <- decrement => 48/decrement-eax
30574     0x11/imm32/alloc-id:fake
30575     _string-decrement/imm32/name
30576     0/imm32/no-inouts
30577     0/imm32/no-inouts
30578     0x11/imm32/alloc-id:fake
30579     Single-int-var-in-eax/imm32/outputs
30580     0x11/imm32/alloc-id:fake
30581     _string_48_decrement_eax/imm32/subx-name
30582     0/imm32/no-rm32
30583     0/imm32/no-r32
30584     0/imm32/no-imm32
30585     0/imm32/no-imm8
30586     0/imm32/no-disp32
30587     0/imm32/no-xm32
30588     0/imm32/no-x32
30589     0x11/imm32/alloc-id:fake
30590     _Primitive-decrement-ecx/imm32/next
30591 _Primitive-decrement-ecx:  # (payload primitive)
30592     0x11/imm32/alloc-id:fake:payload
30593     # var/ecx <- decrement => 49/decrement-ecx
30594     0x11/imm32/alloc-id:fake
30595     _string-decrement/imm32/name
30596     0/imm32/no-inouts
30597     0/imm32/no-inouts
30598     0x11/imm32/alloc-id:fake
30599     Single-int-var-in-ecx/imm32/outputs
30600     0x11/imm32/alloc-id:fake
30601     _string_49_decrement_ecx/imm32/subx-name
30602     0/imm32/no-rm32
30603     0/imm32/no-r32
30604     0/imm32/no-imm32
30605     0/imm32/no-imm8
30606     0/imm32/no-disp32
30607     0/imm32/no-xm32
30608     0/imm32/no-x32
30609     0x11/imm32/alloc-id:fake
30610     _Primitive-decrement-edx/imm32/next
30611 _Primitive-decrement-edx:  # (payload primitive)
30612     0x11/imm32/alloc-id:fake:payload
30613     # var/edx <- decrement => 4a/decrement-edx
30614     0x11/imm32/alloc-id:fake
30615     _string-decrement/imm32/name
30616     0/imm32/no-inouts
30617     0/imm32/no-inouts
30618     0x11/imm32/alloc-id:fake
30619     Single-int-var-in-edx/imm32/outputs
30620     0x11/imm32/alloc-id:fake
30621     _string_4a_decrement_edx/imm32/subx-name
30622     0/imm32/no-rm32
30623     0/imm32/no-r32
30624     0/imm32/no-imm32
30625     0/imm32/no-imm8
30626     0/imm32/no-disp32
30627     0/imm32/no-xm32
30628     0/imm32/no-x32
30629     0x11/imm32/alloc-id:fake
30630     _Primitive-decrement-ebx/imm32/next
30631 _Primitive-decrement-ebx:  # (payload primitive)
30632     0x11/imm32/alloc-id:fake:payload
30633     # var/ebx <- decrement => 4b/decrement-ebx
30634     0x11/imm32/alloc-id:fake
30635     _string-decrement/imm32/name
30636     0/imm32/no-inouts
30637     0/imm32/no-inouts
30638     0x11/imm32/alloc-id:fake
30639     Single-int-var-in-ebx/imm32/outputs
30640     0x11/imm32/alloc-id:fake
30641     _string_4b_decrement_ebx/imm32/subx-name
30642     0/imm32/no-rm32
30643     0/imm32/no-r32
30644     0/imm32/no-imm32
30645     0/imm32/no-imm8
30646     0/imm32/no-disp32
30647     0/imm32/no-xm32
30648     0/imm32/no-x32
30649     0x11/imm32/alloc-id:fake
30650     _Primitive-decrement-esi/imm32/next
30651 _Primitive-decrement-esi:  # (payload primitive)
30652     0x11/imm32/alloc-id:fake:payload
30653     # var/esi <- decrement => 4e/decrement-esi
30654     0x11/imm32/alloc-id:fake
30655     _string-decrement/imm32/name
30656     0/imm32/no-inouts
30657     0/imm32/no-inouts
30658     0x11/imm32/alloc-id:fake
30659     Single-int-var-in-esi/imm32/outputs
30660     0x11/imm32/alloc-id:fake
30661     _string_4e_decrement_esi/imm32/subx-name
30662     0/imm32/no-rm32
30663     0/imm32/no-r32
30664     0/imm32/no-imm32
30665     0/imm32/no-imm8
30666     0/imm32/no-disp32
30667     0/imm32/no-xm32
30668     0/imm32/no-x32
30669     0x11/imm32/alloc-id:fake
30670     _Primitive-decrement-edi/imm32/next
30671 _Primitive-decrement-edi:  # (payload primitive)
30672     0x11/imm32/alloc-id:fake:payload
30673     # var/edi <- decrement => 4f/decrement-edi
30674     0x11/imm32/alloc-id:fake
30675     _string-decrement/imm32/name
30676     0/imm32/no-inouts
30677     0/imm32/no-inouts
30678     0x11/imm32/alloc-id:fake
30679     Single-int-var-in-edi/imm32/outputs
30680     0x11/imm32/alloc-id:fake
30681     _string_4f_decrement_edi/imm32/subx-name
30682     0/imm32/no-rm32
30683     0/imm32/no-r32
30684     0/imm32/no-imm32
30685     0/imm32/no-imm8
30686     0/imm32/no-disp32
30687     0/imm32/no-xm32
30688     0/imm32/no-x32
30689     0x11/imm32/alloc-id:fake
30690     _Primitive-increment-mem/imm32/next
30691 _Primitive-increment-mem:  # (payload primitive)
30692     0x11/imm32/alloc-id:fake:payload
30693     # increment var => ff 0/subop/increment *(ebp+__)
30694     0x11/imm32/alloc-id:fake
30695     _string-increment/imm32/name
30696     0x11/imm32/alloc-id:fake
30697     Single-int-var-in-mem/imm32/inouts
30698     0/imm32/no-outputs
30699     0/imm32/no-outputs
30700     0x11/imm32/alloc-id:fake
30701     _string_ff_subop_increment/imm32/subx-name
30702     1/imm32/rm32-is-first-inout
30703     0/imm32/no-r32
30704     0/imm32/no-imm32
30705     0/imm32/no-imm8
30706     0/imm32/no-disp32
30707     0/imm32/no-xm32
30708     0/imm32/no-x32
30709     0x11/imm32/alloc-id:fake
30710     _Primitive-increment-reg/imm32/next
30711 _Primitive-increment-reg:  # (payload primitive)
30712     0x11/imm32/alloc-id:fake:payload
30713     # var/reg <- increment => ff 0/subop/increment %__
30714     0x11/imm32/alloc-id:fake
30715     _string-increment/imm32/name
30716     0/imm32/no-inouts
30717     0/imm32/no-inouts
30718     0x11/imm32/alloc-id:fake
30719     Single-int-var-in-some-register/imm32/outputs
30720     0x11/imm32/alloc-id:fake
30721     _string_ff_subop_increment/imm32/subx-name
30722     3/imm32/rm32-is-first-output
30723     0/imm32/no-r32
30724     0/imm32/no-imm32
30725     0/imm32/no-imm8
30726     0/imm32/no-disp32
30727     0/imm32/no-xm32
30728     0/imm32/no-x32
30729     0x11/imm32/alloc-id:fake
30730     _Primitive-decrement-mem/imm32/next
30731 _Primitive-decrement-mem:  # (payload primitive)
30732     0x11/imm32/alloc-id:fake:payload
30733     # decrement var => ff 1/subop/decrement *(ebp+__)
30734     0x11/imm32/alloc-id:fake
30735     _string-decrement/imm32/name
30736     0x11/imm32/alloc-id:fake
30737     Single-int-var-in-mem/imm32/inouts
30738     0/imm32/no-outputs
30739     0/imm32/no-outputs
30740     0x11/imm32/alloc-id:fake
30741     _string_ff_subop_decrement/imm32/subx-name
30742     1/imm32/rm32-is-first-inout
30743     0/imm32/no-r32
30744     0/imm32/no-imm32
30745     0/imm32/no-imm8
30746     0/imm32/no-disp32
30747     0/imm32/no-xm32
30748     0/imm32/no-x32
30749     0x11/imm32/alloc-id:fake
30750     _Primitive-decrement-reg/imm32/next
30751 _Primitive-decrement-reg:  # (payload primitive)
30752     0x11/imm32/alloc-id:fake:payload
30753     # var/reg <- decrement => ff 1/subop/decrement %__
30754     0x11/imm32/alloc-id:fake
30755     _string-decrement/imm32/name
30756     0/imm32/no-inouts
30757     0/imm32/no-inouts
30758     0x11/imm32/alloc-id:fake
30759     Single-int-var-in-some-register/imm32/outputs
30760     0x11/imm32/alloc-id:fake
30761     _string_ff_subop_decrement/imm32/subx-name
30762     3/imm32/rm32-is-first-output
30763     0/imm32/no-r32
30764     0/imm32/no-imm32
30765     0/imm32/no-imm8
30766     0/imm32/no-disp32
30767     0/imm32/no-xm32
30768     0/imm32/no-x32
30769     0x11/imm32/alloc-id:fake
30770     _Primitive-add-to-eax/imm32/next
30771 # - add
30772 _Primitive-add-to-eax:  # (payload primitive)
30773     0x11/imm32/alloc-id:fake:payload
30774     # var/eax <- add lit => 05/add-to-eax lit/imm32
30775     0x11/imm32/alloc-id:fake
30776     _string-add/imm32/name
30777     0x11/imm32/alloc-id:fake
30778     Single-lit-var/imm32/inouts
30779     0x11/imm32/alloc-id:fake
30780     Single-int-var-in-eax/imm32/outputs
30781     0x11/imm32/alloc-id:fake
30782     _string_05_add_to_eax/imm32/subx-name
30783     0/imm32/no-rm32
30784     0/imm32/no-r32
30785     1/imm32/imm32-is-first-inout
30786     0/imm32/no-imm8
30787     0/imm32/no-disp32
30788     0/imm32/no-xm32
30789     0/imm32/no-x32
30790     0x11/imm32/alloc-id:fake
30791     _Primitive-add-reg-to-reg/imm32/next
30792 _Primitive-add-reg-to-reg:  # (payload primitive)
30793     0x11/imm32/alloc-id:fake:payload
30794     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
30795     0x11/imm32/alloc-id:fake
30796     _string-add/imm32/name
30797     0x11/imm32/alloc-id:fake
30798     Single-int-var-in-some-register/imm32/inouts
30799     0x11/imm32/alloc-id:fake
30800     Single-int-var-in-some-register/imm32/outputs
30801     0x11/imm32/alloc-id:fake
30802     _string_01_add_to/imm32/subx-name
30803     3/imm32/rm32-is-first-output
30804     1/imm32/r32-is-first-inout
30805     0/imm32/no-imm32
30806     0/imm32/no-imm8
30807     0/imm32/no-disp32
30808     0/imm32/no-xm32
30809     0/imm32/no-x32
30810     0x11/imm32/alloc-id:fake
30811     _Primitive-add-reg-to-mem/imm32/next
30812 _Primitive-add-reg-to-mem:  # (payload primitive)
30813     0x11/imm32/alloc-id:fake:payload
30814     # add-to var1 var2/reg => 01/add-to var1 var2/r32
30815     0x11/imm32/alloc-id:fake
30816     _string-add-to/imm32/name
30817     0x11/imm32/alloc-id:fake
30818     Two-args-int-stack-int-reg/imm32/inouts
30819     0/imm32/no-outputs
30820     0/imm32/no-outputs
30821     0x11/imm32/alloc-id:fake
30822     _string_01_add_to/imm32/subx-name
30823     1/imm32/rm32-is-first-inout
30824     2/imm32/r32-is-second-inout
30825     0/imm32/no-imm32
30826     0/imm32/no-imm8
30827     0/imm32/no-disp32
30828     0/imm32/no-xm32
30829     0/imm32/no-x32
30830     0x11/imm32/alloc-id:fake
30831     _Primitive-add-mem-to-reg/imm32/next
30832 _Primitive-add-mem-to-reg:  # (payload primitive)
30833     0x11/imm32/alloc-id:fake:payload
30834     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
30835     0x11/imm32/alloc-id:fake
30836     _string-add/imm32/name
30837     0x11/imm32/alloc-id:fake
30838     Single-int-var-in-mem/imm32/inouts
30839     0x11/imm32/alloc-id:fake
30840     Single-int-var-in-some-register/imm32/outputs
30841     0x11/imm32/alloc-id:fake
30842     _string_03_add/imm32/subx-name
30843     1/imm32/rm32-is-first-inout
30844     3/imm32/r32-is-first-output
30845     0/imm32/no-imm32
30846     0/imm32/no-imm8
30847     0/imm32/no-disp32
30848     0/imm32/no-xm32
30849     0/imm32/no-x32
30850     0x11/imm32/alloc-id:fake
30851     _Primitive-add-lit-to-reg/imm32/next
30852 _Primitive-add-lit-to-reg:  # (payload primitive)
30853     0x11/imm32/alloc-id:fake:payload
30854     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
30855     0x11/imm32/alloc-id:fake
30856     _string-add/imm32/name
30857     0x11/imm32/alloc-id:fake
30858     Single-lit-var/imm32/inouts
30859     0x11/imm32/alloc-id:fake
30860     Single-int-var-in-some-register/imm32/outputs
30861     0x11/imm32/alloc-id:fake
30862     _string_81_subop_add/imm32/subx-name
30863     3/imm32/rm32-is-first-output
30864     0/imm32/no-r32
30865     1/imm32/imm32-is-first-inout
30866     0/imm32/no-imm8
30867     0/imm32/no-disp32
30868     0/imm32/no-xm32
30869     0/imm32/no-x32
30870     0x11/imm32/alloc-id:fake
30871     _Primitive-add-lit-to-mem/imm32/next
30872 _Primitive-add-lit-to-mem:  # (payload primitive)
30873     0x11/imm32/alloc-id:fake:payload
30874     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
30875     0x11/imm32/alloc-id:fake
30876     _string-add-to/imm32/name
30877     0x11/imm32/alloc-id:fake
30878     Int-var-and-literal/imm32/inouts
30879     0/imm32/no-outputs
30880     0/imm32/no-outputs
30881     0x11/imm32/alloc-id:fake
30882     _string_81_subop_add/imm32/subx-name
30883     1/imm32/rm32-is-first-inout
30884     0/imm32/no-r32
30885     2/imm32/imm32-is-second-inout
30886     0/imm32/no-imm8
30887     0/imm32/no-disp32
30888     0/imm32/no-xm32
30889     0/imm32/no-x32
30890     0x11/imm32/alloc-id:fake
30891     _Primitive-subtract-from-eax/imm32/next
30892 # - subtract
30893 _Primitive-subtract-from-eax:  # (payload primitive)
30894     0x11/imm32/alloc-id:fake:payload
30895     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
30896     0x11/imm32/alloc-id:fake
30897     _string-subtract/imm32/name
30898     0x11/imm32/alloc-id:fake
30899     Single-lit-var/imm32/inouts
30900     0x11/imm32/alloc-id:fake
30901     Single-int-var-in-eax/imm32/outputs
30902     0x11/imm32/alloc-id:fake
30903     _string_2d_subtract_from_eax/imm32/subx-name
30904     0/imm32/no-rm32
30905     0/imm32/no-r32
30906     1/imm32/imm32-is-first-inout
30907     0/imm32/no-imm8
30908     0/imm32/no-disp32
30909     0/imm32/no-xm32
30910     0/imm32/no-x32
30911     0x11/imm32/alloc-id:fake
30912     _Primitive-subtract-reg-from-reg/imm32/next
30913 _Primitive-subtract-reg-from-reg:  # (payload primitive)
30914     0x11/imm32/alloc-id:fake:payload
30915     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
30916     0x11/imm32/alloc-id:fake
30917     _string-subtract/imm32/name
30918     0x11/imm32/alloc-id:fake
30919     Single-int-var-in-some-register/imm32/inouts
30920     0x11/imm32/alloc-id:fake
30921     Single-int-var-in-some-register/imm32/outputs
30922     0x11/imm32/alloc-id:fake
30923     _string_29_subtract_from/imm32/subx-name
30924     3/imm32/rm32-is-first-output
30925     1/imm32/r32-is-first-inout
30926     0/imm32/no-imm32
30927     0/imm32/no-imm8
30928     0/imm32/no-disp32
30929     0/imm32/no-xm32
30930     0/imm32/no-x32
30931     0x11/imm32/alloc-id:fake
30932     _Primitive-subtract-reg-from-mem/imm32/next
30933 _Primitive-subtract-reg-from-mem:  # (payload primitive)
30934     0x11/imm32/alloc-id:fake:payload
30935     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
30936     0x11/imm32/alloc-id:fake
30937     _string-subtract-from/imm32/name
30938     0x11/imm32/alloc-id:fake
30939     Two-args-int-stack-int-reg/imm32/inouts
30940     0/imm32/no-outputs
30941     0/imm32/no-outputs
30942     0x11/imm32/alloc-id:fake
30943     _string_29_subtract_from/imm32/subx-name
30944     1/imm32/rm32-is-first-inout
30945     2/imm32/r32-is-second-inout
30946     0/imm32/no-imm32
30947     0/imm32/no-imm8
30948     0/imm32/no-disp32
30949     0/imm32/no-xm32
30950     0/imm32/no-x32
30951     0x11/imm32/alloc-id:fake
30952     _Primitive-subtract-mem-from-reg/imm32/next
30953 _Primitive-subtract-mem-from-reg:  # (payload primitive)
30954     0x11/imm32/alloc-id:fake:payload
30955     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
30956     0x11/imm32/alloc-id:fake
30957     _string-subtract/imm32/name
30958     0x11/imm32/alloc-id:fake
30959     Single-int-var-in-mem/imm32/inouts
30960     0x11/imm32/alloc-id:fake
30961     Single-int-var-in-some-register/imm32/outputs
30962     0x11/imm32/alloc-id:fake
30963     _string_2b_subtract/imm32/subx-name
30964     1/imm32/rm32-is-first-inout
30965     3/imm32/r32-is-first-output
30966     0/imm32/no-imm32
30967     0/imm32/no-imm8
30968     0/imm32/no-disp32
30969     0/imm32/no-xm32
30970     0/imm32/no-x32
30971     0x11/imm32/alloc-id:fake
30972     _Primitive-subtract-lit-from-reg/imm32/next
30973 _Primitive-subtract-lit-from-reg:  # (payload primitive)
30974     0x11/imm32/alloc-id:fake:payload
30975     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
30976     0x11/imm32/alloc-id:fake
30977     _string-subtract/imm32/name
30978     0x11/imm32/alloc-id:fake
30979     Single-lit-var/imm32/inouts
30980     0x11/imm32/alloc-id:fake
30981     Single-int-var-in-some-register/imm32/outputs
30982     0x11/imm32/alloc-id:fake
30983     _string_81_subop_subtract/imm32/subx-name
30984     3/imm32/rm32-is-first-output
30985     0/imm32/no-r32
30986     1/imm32/imm32-is-first-inout
30987     0/imm32/no-imm8
30988     0/imm32/no-disp32
30989     0/imm32/no-xm32
30990     0/imm32/no-x32
30991     0x11/imm32/alloc-id:fake
30992     _Primitive-subtract-lit-from-mem/imm32/next
30993 _Primitive-subtract-lit-from-mem:  # (payload primitive)
30994     0x11/imm32/alloc-id:fake:payload
30995     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
30996     0x11/imm32/alloc-id:fake
30997     _string-subtract-from/imm32/name
30998     0x11/imm32/alloc-id:fake
30999     Int-var-and-literal/imm32/inouts
31000     0/imm32/no-outputs
31001     0/imm32/no-outputs
31002     0x11/imm32/alloc-id:fake
31003     _string_81_subop_subtract/imm32/subx-name
31004     1/imm32/rm32-is-first-inout
31005     0/imm32/no-r32
31006     2/imm32/imm32-is-second-inout
31007     0/imm32/no-imm8
31008     0/imm32/no-disp32
31009     0/imm32/no-xm32
31010     0/imm32/no-x32
31011     0x11/imm32/alloc-id:fake
31012     _Primitive-and-with-eax/imm32/next
31013 # - and
31014 _Primitive-and-with-eax:  # (payload primitive)
31015     0x11/imm32/alloc-id:fake:payload
31016     # var/eax <- and lit => 25/and-with-eax lit/imm32
31017     0x11/imm32/alloc-id:fake
31018     _string-and/imm32/name
31019     0x11/imm32/alloc-id:fake
31020     Single-lit-var/imm32/inouts
31021     0x11/imm32/alloc-id:fake
31022     Single-int-var-in-eax/imm32/outputs
31023     0x11/imm32/alloc-id:fake
31024     _string_25_and_with_eax/imm32/subx-name
31025     0/imm32/no-rm32
31026     0/imm32/no-r32
31027     1/imm32/imm32-is-first-inout
31028     0/imm32/no-imm8
31029     0/imm32/no-disp32
31030     0/imm32/no-xm32
31031     0/imm32/no-x32
31032     0x11/imm32/alloc-id:fake
31033     _Primitive-and-reg-with-reg/imm32/next
31034 _Primitive-and-reg-with-reg:  # (payload primitive)
31035     0x11/imm32/alloc-id:fake:payload
31036     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
31037     0x11/imm32/alloc-id:fake
31038     _string-and/imm32/name
31039     0x11/imm32/alloc-id:fake
31040     Single-int-var-in-some-register/imm32/inouts
31041     0x11/imm32/alloc-id:fake
31042     Single-int-var-in-some-register/imm32/outputs
31043     0x11/imm32/alloc-id:fake
31044     _string_21_and_with/imm32/subx-name
31045     3/imm32/rm32-is-first-output
31046     1/imm32/r32-is-first-inout
31047     0/imm32/no-imm32
31048     0/imm32/no-imm8
31049     0/imm32/no-disp32
31050     0/imm32/no-xm32
31051     0/imm32/no-x32
31052     0x11/imm32/alloc-id:fake
31053     _Primitive-and-reg-with-mem/imm32/next
31054 _Primitive-and-reg-with-mem:  # (payload primitive)
31055     0x11/imm32/alloc-id:fake:payload
31056     # and-with var1 var2/reg => 21/and-with var1 var2/r32
31057     0x11/imm32/alloc-id:fake
31058     _string-and-with/imm32/name
31059     0x11/imm32/alloc-id:fake
31060     Two-args-int-stack-int-reg/imm32/inouts
31061     0/imm32/no-outputs
31062     0/imm32/no-outputs
31063     0x11/imm32/alloc-id:fake
31064     _string_21_and_with/imm32/subx-name
31065     1/imm32/rm32-is-first-inout
31066     2/imm32/r32-is-second-inout
31067     0/imm32/no-imm32
31068     0/imm32/no-imm8
31069     0/imm32/no-disp32
31070     0/imm32/no-xm32
31071     0/imm32/no-x32
31072     0x11/imm32/alloc-id:fake
31073     _Primitive-and-mem-with-reg/imm32/next
31074 _Primitive-and-mem-with-reg:  # (payload primitive)
31075     0x11/imm32/alloc-id:fake:payload
31076     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
31077     0x11/imm32/alloc-id:fake
31078     _string-and/imm32/name
31079     0x11/imm32/alloc-id:fake
31080     Single-int-var-in-mem/imm32/inouts
31081     0x11/imm32/alloc-id:fake
31082     Single-int-var-in-some-register/imm32/outputs
31083     0x11/imm32/alloc-id:fake
31084     _string_23_and/imm32/subx-name
31085     1/imm32/rm32-is-first-inout
31086     3/imm32/r32-is-first-output
31087     0/imm32/no-imm32
31088     0/imm32/no-imm8
31089     0/imm32/no-disp32
31090     0/imm32/no-xm32
31091     0/imm32/no-x32
31092     0x11/imm32/alloc-id:fake
31093     _Primitive-and-lit-with-reg/imm32/next
31094 _Primitive-and-lit-with-reg:  # (payload primitive)
31095     0x11/imm32/alloc-id:fake:payload
31096     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
31097     0x11/imm32/alloc-id:fake
31098     _string-and/imm32/name
31099     0x11/imm32/alloc-id:fake
31100     Single-lit-var/imm32/inouts
31101     0x11/imm32/alloc-id:fake
31102     Single-int-var-in-some-register/imm32/outputs
31103     0x11/imm32/alloc-id:fake
31104     _string_81_subop_and/imm32/subx-name
31105     3/imm32/rm32-is-first-output
31106     0/imm32/no-r32
31107     1/imm32/imm32-is-first-inout
31108     0/imm32/no-imm8
31109     0/imm32/no-disp32
31110     0/imm32/no-xm32
31111     0/imm32/no-x32
31112     0x11/imm32/alloc-id:fake
31113     _Primitive-and-lit-with-mem/imm32/next
31114 _Primitive-and-lit-with-mem:  # (payload primitive)
31115     0x11/imm32/alloc-id:fake:payload
31116     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
31117     0x11/imm32/alloc-id:fake
31118     _string-and-with/imm32/name
31119     0x11/imm32/alloc-id:fake
31120     Int-var-and-literal/imm32/inouts
31121     0/imm32/no-outputs
31122     0/imm32/no-outputs
31123     0x11/imm32/alloc-id:fake
31124     _string_81_subop_and/imm32/subx-name
31125     1/imm32/rm32-is-first-inout
31126     0/imm32/no-r32
31127     2/imm32/imm32-is-second-inout
31128     0/imm32/no-imm8
31129     0/imm32/no-disp32
31130     0/imm32/no-xm32
31131     0/imm32/no-x32
31132     0x11/imm32/alloc-id:fake
31133     _Primitive-or-with-eax/imm32/next
31134 # - or
31135 _Primitive-or-with-eax:  # (payload primitive)
31136     0x11/imm32/alloc-id:fake:payload
31137     # var/eax <- or lit => 0d/or-with-eax lit/imm32
31138     0x11/imm32/alloc-id:fake
31139     _string-or/imm32/name
31140     0x11/imm32/alloc-id:fake
31141     Single-lit-var/imm32/inouts
31142     0x11/imm32/alloc-id:fake
31143     Single-int-var-in-eax/imm32/outputs
31144     0x11/imm32/alloc-id:fake
31145     _string_0d_or_with_eax/imm32/subx-name
31146     0/imm32/no-rm32
31147     0/imm32/no-r32
31148     1/imm32/imm32-is-first-inout
31149     0/imm32/no-imm8
31150     0/imm32/no-disp32
31151     0/imm32/no-xm32
31152     0/imm32/no-x32
31153     0x11/imm32/alloc-id:fake
31154     _Primitive-or-reg-with-reg/imm32/next
31155 _Primitive-or-reg-with-reg:  # (payload primitive)
31156     0x11/imm32/alloc-id:fake:payload
31157     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
31158     0x11/imm32/alloc-id:fake
31159     _string-or/imm32/name
31160     0x11/imm32/alloc-id:fake
31161     Single-int-var-in-some-register/imm32/inouts
31162     0x11/imm32/alloc-id:fake
31163     Single-int-var-in-some-register/imm32/outputs
31164     0x11/imm32/alloc-id:fake
31165     _string_09_or_with/imm32/subx-name
31166     3/imm32/rm32-is-first-output
31167     1/imm32/r32-is-first-inout
31168     0/imm32/no-imm32
31169     0/imm32/no-imm8
31170     0/imm32/no-disp32
31171     0/imm32/no-xm32
31172     0/imm32/no-x32
31173     0x11/imm32/alloc-id:fake
31174     _Primitive-or-reg-with-mem/imm32/next
31175 _Primitive-or-reg-with-mem:  # (payload primitive)
31176     0x11/imm32/alloc-id:fake:payload
31177     # or-with var1 var2/reg => 09/or-with var1 var2/r32
31178     0x11/imm32/alloc-id:fake
31179     _string-or-with/imm32/name
31180     0x11/imm32/alloc-id:fake
31181     Two-args-int-stack-int-reg/imm32/inouts
31182     0/imm32/no-outputs
31183     0/imm32/no-outputs
31184     0x11/imm32/alloc-id:fake
31185     _string_09_or_with/imm32/subx-name
31186     1/imm32/rm32-is-first-inout
31187     2/imm32/r32-is-second-inout
31188     0/imm32/no-imm32
31189     0/imm32/no-imm8
31190     0/imm32/no-disp32
31191     0/imm32/no-xm32
31192     0/imm32/no-x32
31193     0x11/imm32/alloc-id:fake
31194     _Primitive-or-mem-with-reg/imm32/next
31195 _Primitive-or-mem-with-reg:  # (payload primitive)
31196     0x11/imm32/alloc-id:fake:payload
31197     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
31198     0x11/imm32/alloc-id:fake
31199     _string-or/imm32/name
31200     0x11/imm32/alloc-id:fake
31201     Single-int-var-in-mem/imm32/inouts
31202     0x11/imm32/alloc-id:fake
31203     Single-int-var-in-some-register/imm32/outputs
31204     0x11/imm32/alloc-id:fake
31205     _string_0b_or/imm32/subx-name
31206     1/imm32/rm32-is-first-inout
31207     3/imm32/r32-is-first-output
31208     0/imm32/no-imm32
31209     0/imm32/no-imm8
31210     0/imm32/no-disp32
31211     0/imm32/no-xm32
31212     0/imm32/no-x32
31213     0x11/imm32/alloc-id:fake
31214     _Primitive-or-lit-with-reg/imm32/next
31215 _Primitive-or-lit-with-reg:  # (payload primitive)
31216     0x11/imm32/alloc-id:fake:payload
31217     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
31218     0x11/imm32/alloc-id:fake
31219     _string-or/imm32/name
31220     0x11/imm32/alloc-id:fake
31221     Single-lit-var/imm32/inouts
31222     0x11/imm32/alloc-id:fake
31223     Single-int-var-in-some-register/imm32/outputs
31224     0x11/imm32/alloc-id:fake
31225     _string_81_subop_or/imm32/subx-name
31226     3/imm32/rm32-is-first-output
31227     0/imm32/no-r32
31228     1/imm32/imm32-is-first-inout
31229     0/imm32/no-imm8
31230     0/imm32/no-disp32
31231     0/imm32/no-xm32
31232     0/imm32/no-x32
31233     0x11/imm32/alloc-id:fake
31234     _Primitive-or-lit-with-mem/imm32/next
31235 _Primitive-or-lit-with-mem:  # (payload primitive)
31236     0x11/imm32/alloc-id:fake:payload
31237     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
31238     0x11/imm32/alloc-id:fake
31239     _string-or-with/imm32/name
31240     0x11/imm32/alloc-id:fake
31241     Int-var-and-literal/imm32/inouts
31242     0/imm32/no-outputs
31243     0/imm32/no-outputs
31244     0x11/imm32/alloc-id:fake
31245     _string_81_subop_or/imm32/subx-name
31246     1/imm32/rm32-is-first-inout
31247     0/imm32/no-r32
31248     2/imm32/imm32-is-second-inout
31249     0/imm32/no-imm8
31250     0/imm32/no-disp32
31251     0/imm32/no-xm32
31252     0/imm32/no-x32
31253     0x11/imm32/alloc-id:fake
31254     _Primitive-not-reg/imm32/next
31255 # - not
31256 _Primitive-not-reg:  # (payload primitive)
31257     0x11/imm32/alloc-id:fake:payload
31258     # var1/reg <- not => f7 2/subop/not var1/rm32
31259     0x11/imm32/alloc-id:fake
31260     _string-not/imm32/name
31261     0/imm32/no-inouts
31262     0/imm32/no-inouts
31263     0x11/imm32/alloc-id:fake
31264     Single-int-var-in-some-register/imm32/outputs
31265     0x11/imm32/alloc-id:fake
31266     _string_f7_subop_not/imm32/subx-name
31267     3/imm32/rm32-is-first-output
31268     0/imm32/no-r32
31269     0/imm32/no-imm32
31270     0/imm32/no-imm8
31271     0/imm32/no-disp32
31272     0/imm32/no-xm32
31273     0/imm32/no-x32
31274     0x11/imm32/alloc-id:fake
31275     _Primitive-not-mem/imm32/next
31276 _Primitive-not-mem:  # (payload primitive)
31277     0x11/imm32/alloc-id:fake:payload
31278     # not var1 => f7 2/subop/not var1/rm32
31279     0x11/imm32/alloc-id:fake
31280     _string-not/imm32/name
31281     0x11/imm32/alloc-id:fake
31282     Single-int-var-in-mem/imm32/inouts
31283     0/imm32/no-outputs
31284     0/imm32/no-outputs
31285     0x11/imm32/alloc-id:fake
31286     _string_f7_subop_not/imm32/subx-name
31287     1/imm32/rm32-is-first-inout
31288     0/imm32/no-r32
31289     0/imm32/no-imm32
31290     0/imm32/no-imm8
31291     0/imm32/no-disp32
31292     0/imm32/no-xm32
31293     0/imm32/no-x32
31294     0x11/imm32/alloc-id:fake
31295     _Primitive-xor-with-eax/imm32/next
31296 # - xor
31297 _Primitive-xor-with-eax:  # (payload primitive)
31298     0x11/imm32/alloc-id:fake:payload
31299     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
31300     0x11/imm32/alloc-id:fake
31301     _string-xor/imm32/name
31302     0x11/imm32/alloc-id:fake
31303     Single-lit-var/imm32/inouts
31304     0x11/imm32/alloc-id:fake
31305     Single-int-var-in-eax/imm32/outputs
31306     0x11/imm32/alloc-id:fake
31307     _string_35_xor_with_eax/imm32/subx-name
31308     0/imm32/no-rm32
31309     0/imm32/no-r32
31310     1/imm32/imm32-is-first-inout
31311     0/imm32/no-imm8
31312     0/imm32/no-disp32
31313     0/imm32/no-xm32
31314     0/imm32/no-x32
31315     0x11/imm32/alloc-id:fake
31316     _Primitive-xor-reg-with-reg/imm32/next
31317 _Primitive-xor-reg-with-reg:  # (payload primitive)
31318     0x11/imm32/alloc-id:fake:payload
31319     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
31320     0x11/imm32/alloc-id:fake
31321     _string-xor/imm32/name
31322     0x11/imm32/alloc-id:fake
31323     Single-int-var-in-some-register/imm32/inouts
31324     0x11/imm32/alloc-id:fake
31325     Single-int-var-in-some-register/imm32/outputs
31326     0x11/imm32/alloc-id:fake
31327     _string_31_xor_with/imm32/subx-name
31328     3/imm32/rm32-is-first-output
31329     1/imm32/r32-is-first-inout
31330     0/imm32/no-imm32
31331     0/imm32/no-imm8
31332     0/imm32/no-disp32
31333     0/imm32/no-xm32
31334     0/imm32/no-x32
31335     0x11/imm32/alloc-id:fake
31336     _Primitive-xor-reg-with-mem/imm32/next
31337 _Primitive-xor-reg-with-mem:  # (payload primitive)
31338     0x11/imm32/alloc-id:fake:payload
31339     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
31340     0x11/imm32/alloc-id:fake
31341     _string-xor-with/imm32/name
31342     0x11/imm32/alloc-id:fake
31343     Two-args-int-stack-int-reg/imm32/inouts
31344     0/imm32/no-outputs
31345     0/imm32/no-outputs
31346     0x11/imm32/alloc-id:fake
31347     _string_31_xor_with/imm32/subx-name
31348     1/imm32/rm32-is-first-inout
31349     2/imm32/r32-is-second-inout
31350     0/imm32/no-imm32
31351     0/imm32/no-imm8
31352     0/imm32/no-disp32
31353     0/imm32/no-xm32
31354     0/imm32/no-x32
31355     0x11/imm32/alloc-id:fake
31356     _Primitive-xor-mem-with-reg/imm32/next
31357 _Primitive-xor-mem-with-reg:  # (payload primitive)
31358     0x11/imm32/alloc-id:fake:payload
31359     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
31360     0x11/imm32/alloc-id:fake
31361     _string-xor/imm32/name
31362     0x11/imm32/alloc-id:fake
31363     Single-int-var-in-mem/imm32/inouts
31364     0x11/imm32/alloc-id:fake
31365     Single-int-var-in-some-register/imm32/outputs
31366     0x11/imm32/alloc-id:fake
31367     _string_33_xor/imm32/subx-name
31368     1/imm32/rm32-is-first-inout
31369     3/imm32/r32-is-first-output
31370     0/imm32/no-imm32
31371     0/imm32/no-imm8
31372     0/imm32/no-disp32
31373     0/imm32/no-xm32
31374     0/imm32/no-x32
31375     0x11/imm32/alloc-id:fake
31376     _Primitive-xor-lit-with-reg/imm32/next
31377 _Primitive-xor-lit-with-reg:  # (payload primitive)
31378     0x11/imm32/alloc-id:fake:payload
31379     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
31380     0x11/imm32/alloc-id:fake
31381     _string-xor/imm32/name
31382     0x11/imm32/alloc-id:fake
31383     Single-lit-var/imm32/inouts
31384     0x11/imm32/alloc-id:fake
31385     Single-int-var-in-some-register/imm32/outputs
31386     0x11/imm32/alloc-id:fake
31387     _string_81_subop_xor/imm32/subx-name
31388     3/imm32/rm32-is-first-output
31389     0/imm32/no-r32
31390     1/imm32/imm32-is-first-inout
31391     0/imm32/no-imm8
31392     0/imm32/no-disp32
31393     0/imm32/no-xm32
31394     0/imm32/no-x32
31395     0x11/imm32/alloc-id:fake
31396     _Primitive-xor-lit-with-mem/imm32/next
31397 _Primitive-xor-lit-with-mem:  # (payload primitive)
31398     0x11/imm32/alloc-id:fake:payload
31399     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
31400     0x11/imm32/alloc-id:fake
31401     _string-xor-with/imm32/name
31402     0x11/imm32/alloc-id:fake
31403     Int-var-and-literal/imm32/inouts
31404     0/imm32/no-outputs
31405     0/imm32/no-outputs
31406     0x11/imm32/alloc-id:fake
31407     _string_81_subop_xor/imm32/subx-name
31408     1/imm32/rm32-is-first-inout
31409     0/imm32/no-r32
31410     2/imm32/imm32-is-second-inout
31411     0/imm32/no-imm8
31412     0/imm32/no-disp32
31413     0/imm32/no-xm32
31414     0/imm32/no-x32
31415     0x11/imm32/alloc-id:fake
31416     _Primitive-shift-reg-left-by-lit/imm32/next
31417 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
31418     0x11/imm32/alloc-id:fake:payload
31419     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31420     0x11/imm32/alloc-id:fake
31421     _string-shift-left/imm32/name
31422     0x11/imm32/alloc-id:fake
31423     Single-lit-var/imm32/inouts
31424     0x11/imm32/alloc-id:fake
31425     Single-int-var-in-some-register/imm32/outputs
31426     0x11/imm32/alloc-id:fake
31427     _string_c1_subop_shift_left/imm32/subx-name
31428     3/imm32/rm32-is-first-output
31429     0/imm32/no-r32
31430     0/imm32/no-imm32
31431     1/imm32/imm8-is-first-inout
31432     0/imm32/no-disp32
31433     0/imm32/no-xm32
31434     0/imm32/no-x32
31435     0x11/imm32/alloc-id:fake
31436     _Primitive-shift-reg-right-by-lit/imm32/next
31437 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
31438     0x11/imm32/alloc-id:fake:payload
31439     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31440     0x11/imm32/alloc-id:fake
31441     _string-shift-right/imm32/name
31442     0x11/imm32/alloc-id:fake
31443     Single-lit-var/imm32/inouts
31444     0x11/imm32/alloc-id:fake
31445     Single-int-var-in-some-register/imm32/outputs
31446     0x11/imm32/alloc-id:fake
31447     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31448     3/imm32/rm32-is-first-output
31449     0/imm32/no-r32
31450     0/imm32/no-imm32
31451     1/imm32/imm8-is-first-inout
31452     0/imm32/no-disp32
31453     0/imm32/no-xm32
31454     0/imm32/no-x32
31455     0x11/imm32/alloc-id:fake
31456     _Primitive-shift-reg-right-signed-by-lit/imm32/next
31457 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
31458     0x11/imm32/alloc-id:fake:payload
31459     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31460     0x11/imm32/alloc-id:fake
31461     _string-shift-right-signed/imm32/name
31462     0x11/imm32/alloc-id:fake
31463     Single-lit-var/imm32/inouts
31464     0x11/imm32/alloc-id:fake
31465     Single-int-var-in-some-register/imm32/outputs
31466     0x11/imm32/alloc-id:fake
31467     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31468     3/imm32/rm32-is-first-output
31469     0/imm32/no-r32
31470     0/imm32/no-imm32
31471     1/imm32/imm8-is-first-inout
31472     0/imm32/no-disp32
31473     0/imm32/no-xm32
31474     0/imm32/no-x32
31475     0x11/imm32/alloc-id:fake
31476     _Primitive-shift-mem-left-by-lit/imm32/next
31477 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
31478     0x11/imm32/alloc-id:fake:payload
31479     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
31480     0x11/imm32/alloc-id:fake
31481     _string-shift-left/imm32/name
31482     0x11/imm32/alloc-id:fake
31483     Int-var-and-literal/imm32/inouts
31484     0/imm32/no-outputs
31485     0/imm32/no-outputs
31486     0x11/imm32/alloc-id:fake
31487     _string_c1_subop_shift_left/imm32/subx-name
31488     1/imm32/rm32-is-first-inout
31489     0/imm32/no-r32
31490     0/imm32/no-imm32
31491     2/imm32/imm8-is-second-inout
31492     0/imm32/no-disp32
31493     0/imm32/no-xm32
31494     0/imm32/no-x32
31495     0x11/imm32/alloc-id:fake
31496     _Primitive-shift-mem-right-by-lit/imm32/next
31497 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
31498     0x11/imm32/alloc-id:fake:payload
31499     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
31500     0x11/imm32/alloc-id:fake
31501     _string-shift-right/imm32/name
31502     0x11/imm32/alloc-id:fake
31503     Int-var-and-literal/imm32/inouts
31504     0/imm32/no-outputs
31505     0/imm32/no-outputs
31506     0x11/imm32/alloc-id:fake
31507     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
31508     1/imm32/rm32-is-first-inout
31509     0/imm32/no-r32
31510     0/imm32/no-imm32
31511     2/imm32/imm8-is-second-inout
31512     0/imm32/no-disp32
31513     0/imm32/no-xm32
31514     0/imm32/no-x32
31515     0x11/imm32/alloc-id:fake
31516     _Primitive-shift-mem-right-signed-by-lit/imm32/next
31517 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
31518     0x11/imm32/alloc-id:fake:payload
31519     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
31520     0x11/imm32/alloc-id:fake
31521     _string-shift-right-signed/imm32/name
31522     0x11/imm32/alloc-id:fake
31523     Int-var-and-literal/imm32/inouts
31524     0/imm32/no-outputs
31525     0/imm32/no-outputs
31526     0x11/imm32/alloc-id:fake
31527     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
31528     1/imm32/rm32-is-first-inout
31529     0/imm32/no-r32
31530     0/imm32/no-imm32
31531     2/imm32/imm8-is-second-inout
31532     0/imm32/no-disp32
31533     0/imm32/no-xm32
31534     0/imm32/no-x32
31535     0x11/imm32/alloc-id:fake
31536     _Primitive-copy-to-eax/imm32/next
31537 # - copy
31538 _Primitive-copy-to-eax:  # (payload primitive)
31539     0x11/imm32/alloc-id:fake:payload
31540     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
31541     0x11/imm32/alloc-id:fake
31542     _string-copy/imm32/name
31543     0x11/imm32/alloc-id:fake
31544     Single-lit-var/imm32/inouts
31545     0x11/imm32/alloc-id:fake
31546     Single-int-var-in-eax/imm32/outputs
31547     0x11/imm32/alloc-id:fake
31548     _string_b8_copy_to_eax/imm32/subx-name
31549     0/imm32/no-rm32
31550     0/imm32/no-r32
31551     1/imm32/imm32-is-first-inout
31552     0/imm32/no-imm8
31553     0/imm32/no-disp32
31554     0/imm32/no-xm32
31555     0/imm32/no-x32
31556     0x11/imm32/alloc-id:fake
31557     _Primitive-copy-to-ecx/imm32/next
31558 _Primitive-copy-to-ecx:  # (payload primitive)
31559     0x11/imm32/alloc-id:fake:payload
31560     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
31561     0x11/imm32/alloc-id:fake
31562     _string-copy/imm32/name
31563     0x11/imm32/alloc-id:fake
31564     Single-lit-var/imm32/inouts
31565     0x11/imm32/alloc-id:fake
31566     Single-int-var-in-ecx/imm32/outputs
31567     0x11/imm32/alloc-id:fake
31568     _string_b9_copy_to_ecx/imm32/subx-name
31569     0/imm32/no-rm32
31570     0/imm32/no-r32
31571     1/imm32/imm32-is-first-inout
31572     0/imm32/no-imm8
31573     0/imm32/no-disp32
31574     0/imm32/no-xm32
31575     0/imm32/no-x32
31576     0x11/imm32/alloc-id:fake
31577     _Primitive-copy-to-edx/imm32/next
31578 _Primitive-copy-to-edx:  # (payload primitive)
31579     0x11/imm32/alloc-id:fake:payload
31580     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
31581     0x11/imm32/alloc-id:fake
31582     _string-copy/imm32/name
31583     0x11/imm32/alloc-id:fake
31584     Single-lit-var/imm32/inouts
31585     0x11/imm32/alloc-id:fake
31586     Single-int-var-in-edx/imm32/outputs
31587     0x11/imm32/alloc-id:fake
31588     _string_ba_copy_to_edx/imm32/subx-name
31589     0/imm32/no-rm32
31590     0/imm32/no-r32
31591     1/imm32/imm32-is-first-inout
31592     0/imm32/no-imm8
31593     0/imm32/no-disp32
31594     0/imm32/no-xm32
31595     0/imm32/no-x32
31596     0x11/imm32/alloc-id:fake
31597     _Primitive-copy-to-ebx/imm32/next
31598 _Primitive-copy-to-ebx:  # (payload primitive)
31599     0x11/imm32/alloc-id:fake:payload
31600     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
31601     0x11/imm32/alloc-id:fake
31602     _string-copy/imm32/name
31603     0x11/imm32/alloc-id:fake
31604     Single-lit-var/imm32/inouts
31605     0x11/imm32/alloc-id:fake
31606     Single-int-var-in-ebx/imm32/outputs
31607     0x11/imm32/alloc-id:fake
31608     _string_bb_copy_to_ebx/imm32/subx-name
31609     0/imm32/no-rm32
31610     0/imm32/no-r32
31611     1/imm32/imm32-is-first-inout
31612     0/imm32/no-imm8
31613     0/imm32/no-disp32
31614     0/imm32/no-xm32
31615     0/imm32/no-x32
31616     0x11/imm32/alloc-id:fake
31617     _Primitive-copy-to-esi/imm32/next
31618 _Primitive-copy-to-esi:  # (payload primitive)
31619     0x11/imm32/alloc-id:fake:payload
31620     # var/esi <- copy lit => be/copy-to-esi lit/imm32
31621     0x11/imm32/alloc-id:fake
31622     _string-copy/imm32/name
31623     0x11/imm32/alloc-id:fake
31624     Single-lit-var/imm32/inouts
31625     0x11/imm32/alloc-id:fake
31626     Single-int-var-in-esi/imm32/outputs
31627     0x11/imm32/alloc-id:fake
31628     _string_be_copy_to_esi/imm32/subx-name
31629     0/imm32/no-rm32
31630     0/imm32/no-r32
31631     1/imm32/imm32-is-first-inout
31632     0/imm32/no-imm8
31633     0/imm32/no-disp32
31634     0/imm32/no-xm32
31635     0/imm32/no-x32
31636     0x11/imm32/alloc-id:fake
31637     _Primitive-copy-to-edi/imm32/next
31638 _Primitive-copy-to-edi:  # (payload primitive)
31639     0x11/imm32/alloc-id:fake:payload
31640     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
31641     0x11/imm32/alloc-id:fake
31642     _string-copy/imm32/name
31643     0x11/imm32/alloc-id:fake
31644     Single-lit-var/imm32/inouts
31645     0x11/imm32/alloc-id:fake
31646     Single-int-var-in-edi/imm32/outputs
31647     0x11/imm32/alloc-id:fake
31648     _string_bf_copy_to_edi/imm32/subx-name
31649     0/imm32/no-rm32
31650     0/imm32/no-r32
31651     1/imm32/imm32-is-first-inout
31652     0/imm32/no-imm8
31653     0/imm32/no-disp32
31654     0/imm32/no-xm32
31655     0/imm32/no-x32
31656     0x11/imm32/alloc-id:fake
31657     _Primitive-copy-reg-to-reg/imm32/next
31658 _Primitive-copy-reg-to-reg:  # (payload primitive)
31659     0x11/imm32/alloc-id:fake:payload
31660     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
31661     0x11/imm32/alloc-id:fake
31662     _string-copy/imm32/name
31663     0x11/imm32/alloc-id:fake
31664     Single-int-var-in-some-register/imm32/inouts
31665     0x11/imm32/alloc-id:fake
31666     Single-int-var-in-some-register/imm32/outputs
31667     0x11/imm32/alloc-id:fake
31668     _string_89_<-/imm32/subx-name
31669     3/imm32/rm32-is-first-output
31670     1/imm32/r32-is-first-inout
31671     0/imm32/no-imm32
31672     0/imm32/no-imm8
31673     0/imm32/no-disp32
31674     0/imm32/no-xm32
31675     0/imm32/no-x32
31676     0x11/imm32/alloc-id:fake
31677     _Primitive-copy-reg-to-mem/imm32/next
31678 _Primitive-copy-reg-to-mem:  # (payload primitive)
31679     0x11/imm32/alloc-id:fake:payload
31680     # copy-to var1 var2/reg => 89/<- var1 var2/r32
31681     0x11/imm32/alloc-id:fake
31682     _string-copy-to/imm32/name
31683     0x11/imm32/alloc-id:fake
31684     Two-args-int-stack-int-reg/imm32/inouts
31685     0/imm32/no-outputs
31686     0/imm32/no-outputs
31687     0x11/imm32/alloc-id:fake
31688     _string_89_<-/imm32/subx-name
31689     1/imm32/rm32-is-first-inout
31690     2/imm32/r32-is-second-inout
31691     0/imm32/no-imm32
31692     0/imm32/no-imm8
31693     0/imm32/no-disp32
31694     0/imm32/no-xm32
31695     0/imm32/no-x32
31696     0x11/imm32/alloc-id:fake
31697     _Primitive-copy-mem-to-reg/imm32/next
31698 _Primitive-copy-mem-to-reg:  # (payload primitive)
31699     0x11/imm32/alloc-id:fake:payload
31700     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
31701     0x11/imm32/alloc-id:fake
31702     _string-copy/imm32/name
31703     0x11/imm32/alloc-id:fake
31704     Single-int-var-in-mem/imm32/inouts
31705     0x11/imm32/alloc-id:fake
31706     Single-int-var-in-some-register/imm32/outputs
31707     0x11/imm32/alloc-id:fake
31708     _string_8b_->/imm32/subx-name
31709     1/imm32/rm32-is-first-inout
31710     3/imm32/r32-is-first-output
31711     0/imm32/no-imm32
31712     0/imm32/no-imm8
31713     0/imm32/no-disp32
31714     0/imm32/no-xm32
31715     0/imm32/no-x32
31716     0x11/imm32/alloc-id:fake
31717     _Primitive-copy-lit-to-reg/imm32/next
31718 _Primitive-copy-lit-to-reg:  # (payload primitive)
31719     0x11/imm32/alloc-id:fake:payload
31720     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
31721     0x11/imm32/alloc-id:fake
31722     _string-copy/imm32/name
31723     0x11/imm32/alloc-id:fake
31724     Single-lit-var/imm32/inouts
31725     0x11/imm32/alloc-id:fake
31726     Single-int-var-in-some-register/imm32/outputs
31727     0x11/imm32/alloc-id:fake
31728     _string_c7_subop_copy/imm32/subx-name
31729     3/imm32/rm32-is-first-output
31730     0/imm32/no-r32
31731     1/imm32/imm32-is-first-inout
31732     0/imm32/no-imm8
31733     0/imm32/no-disp32
31734     0/imm32/no-xm32
31735     0/imm32/no-x32
31736     0x11/imm32/alloc-id:fake
31737     _Primitive-copy-lit-to-mem/imm32/next
31738 _Primitive-copy-lit-to-mem:  # (payload primitive)
31739     0x11/imm32/alloc-id:fake:payload
31740     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
31741     0x11/imm32/alloc-id:fake
31742     _string-copy-to/imm32/name
31743     0x11/imm32/alloc-id:fake
31744     Int-var-and-literal/imm32/inouts
31745     0/imm32/no-outputs
31746     0/imm32/no-outputs
31747     0x11/imm32/alloc-id:fake
31748     _string_c7_subop_copy/imm32/subx-name
31749     1/imm32/rm32-is-first-inout
31750     0/imm32/no-r32
31751     2/imm32/imm32-is-second-inout
31752     0/imm32/no-imm8
31753     0/imm32/no-disp32
31754     0/imm32/no-xm32
31755     0/imm32/no-x32
31756     0x11/imm32/alloc-id:fake
31757     _Primitive-copy-byte-from-reg/imm32/next
31758 # - copy byte
31759 _Primitive-copy-byte-from-reg:
31760     0x11/imm32/alloc-id:fake:payload
31761     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
31762     0x11/imm32/alloc-id:fake
31763     _string-copy-byte/imm32/name
31764     0x11/imm32/alloc-id:fake
31765     Single-byte-var-in-some-register/imm32/inouts
31766     0x11/imm32/alloc-id:fake
31767     Single-byte-var-in-some-register/imm32/outputs
31768     0x11/imm32/alloc-id:fake
31769     _string_8a_copy_byte/imm32/subx-name
31770     1/imm32/rm32-is-first-inout
31771     3/imm32/r32-is-first-output
31772     0/imm32/no-imm32
31773     0/imm32/no-imm8
31774     0/imm32/no-disp32
31775     0/imm32/no-xm32
31776     0/imm32/no-x32
31777     0x11/imm32/alloc-id:fake
31778     _Primitive-copy-byte-from-mem/imm32/next
31779 _Primitive-copy-byte-from-mem:
31780     0x11/imm32/alloc-id:fake:payload
31781     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
31782     0x11/imm32/alloc-id:fake
31783     _string-copy-byte/imm32/name
31784     0x11/imm32/alloc-id:fake
31785     Single-byte-var-in-mem/imm32/inouts
31786     0x11/imm32/alloc-id:fake
31787     Single-byte-var-in-some-register/imm32/outputs
31788     0x11/imm32/alloc-id:fake
31789     _string_8a_copy_byte/imm32/subx-name
31790     1/imm32/rm32-is-first-inout
31791     3/imm32/r32-is-first-output
31792     0/imm32/no-imm32
31793     0/imm32/no-imm8
31794     0/imm32/no-disp32
31795     0/imm32/no-xm32
31796     0/imm32/no-x32
31797     0x11/imm32/alloc-id:fake
31798     _Primitive-copy-byte-to-mem/imm32/next
31799 _Primitive-copy-byte-to-mem:
31800     0x11/imm32/alloc-id:fake:payload
31801     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
31802     0x11/imm32/alloc-id:fake
31803     _string-copy-byte-to/imm32/name
31804     0x11/imm32/alloc-id:fake
31805     Two-args-byte-stack-byte-reg/imm32/inouts
31806     0/imm32/no-outputs
31807     0/imm32/no-outputs
31808     0x11/imm32/alloc-id:fake
31809     _string_88_copy_byte/imm32/subx-name
31810     1/imm32/rm32-is-first-inout
31811     2/imm32/r32-is-second-inout
31812     0/imm32/no-imm32
31813     0/imm32/no-imm8
31814     0/imm32/no-disp32
31815     0/imm32/no-xm32
31816     0/imm32/no-x32
31817     0x11/imm32/alloc-id:fake
31818     _Primitive-address/imm32/next
31819 # - address
31820 _Primitive-address:  # (payload primitive)
31821     0x11/imm32/alloc-id:fake:payload
31822     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
31823     0x11/imm32/alloc-id:fake
31824     _string-address/imm32/name
31825     0x11/imm32/alloc-id:fake
31826     Single-int-var-in-mem/imm32/inouts
31827     0x11/imm32/alloc-id:fake
31828     Single-addr-var-in-some-register/imm32/outputs
31829     0x11/imm32/alloc-id:fake
31830     _string_8d_copy_address/imm32/subx-name
31831     1/imm32/rm32-is-first-inout
31832     3/imm32/r32-is-first-output
31833     0/imm32/no-imm32
31834     0/imm32/no-imm8
31835     0/imm32/no-disp32
31836     0/imm32/no-xm32
31837     0/imm32/no-x32
31838     0x11/imm32/alloc-id:fake
31839     _Primitive-compare-reg-with-reg/imm32/next
31840 # - compare
31841 _Primitive-compare-reg-with-reg:  # (payload primitive)
31842     0x11/imm32/alloc-id:fake:payload
31843     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
31844     0x11/imm32/alloc-id:fake
31845     _string-compare/imm32/name
31846     0x11/imm32/alloc-id:fake
31847     Two-int-args-in-regs/imm32/inouts
31848     0/imm32/no-outputs
31849     0/imm32/no-outputs
31850     0x11/imm32/alloc-id:fake
31851     _string_39_compare->/imm32/subx-name
31852     1/imm32/rm32-is-first-inout
31853     2/imm32/r32-is-second-inout
31854     0/imm32/no-imm32
31855     0/imm32/no-imm8
31856     0/imm32/no-disp32
31857     0/imm32/no-xm32
31858     0/imm32/no-x32
31859     0x11/imm32/alloc-id:fake
31860     _Primitive-compare-mem-with-reg/imm32/next
31861 _Primitive-compare-mem-with-reg:  # (payload primitive)
31862     0x11/imm32/alloc-id:fake:payload
31863     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
31864     0x11/imm32/alloc-id:fake
31865     _string-compare/imm32/name
31866     0x11/imm32/alloc-id:fake
31867     Two-args-int-stack-int-reg/imm32/inouts
31868     0/imm32/no-outputs
31869     0/imm32/no-outputs
31870     0x11/imm32/alloc-id:fake
31871     _string_39_compare->/imm32/subx-name
31872     1/imm32/rm32-is-first-inout
31873     2/imm32/r32-is-second-inout
31874     0/imm32/no-imm32
31875     0/imm32/no-imm8
31876     0/imm32/no-disp32
31877     0/imm32/no-xm32
31878     0/imm32/no-x32
31879     0x11/imm32/alloc-id:fake
31880     _Primitive-compare-reg-with-mem/imm32/next
31881 _Primitive-compare-reg-with-mem:  # (payload primitive)
31882     0x11/imm32/alloc-id:fake:payload
31883     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
31884     0x11/imm32/alloc-id:fake
31885     _string-compare/imm32/name
31886     0x11/imm32/alloc-id:fake
31887     Two-args-int-reg-int-stack/imm32/inouts
31888     0/imm32/no-outputs
31889     0/imm32/no-outputs
31890     0x11/imm32/alloc-id:fake
31891     _string_3b_compare<-/imm32/subx-name
31892     2/imm32/rm32-is-second-inout
31893     1/imm32/r32-is-first-inout
31894     0/imm32/no-imm32
31895     0/imm32/no-imm8
31896     0/imm32/no-disp32
31897     0/imm32/no-xm32
31898     0/imm32/no-x32
31899     0x11/imm32/alloc-id:fake
31900     _Primitive-compare-eax-with-literal/imm32/next
31901 _Primitive-compare-eax-with-literal:  # (payload primitive)
31902     0x11/imm32/alloc-id:fake:payload
31903     # compare var1/eax n => 3d/compare-eax-with n/imm32
31904     0x11/imm32/alloc-id:fake
31905     _string-compare/imm32/name
31906     0x11/imm32/alloc-id:fake
31907     Two-args-int-eax-int-literal/imm32/inouts
31908     0/imm32/no-outputs
31909     0/imm32/no-outputs
31910     0x11/imm32/alloc-id:fake
31911     _string_3d_compare_eax_with/imm32/subx-name
31912     0/imm32/no-rm32
31913     0/imm32/no-r32
31914     2/imm32/imm32-is-second-inout
31915     0/imm32/no-imm8
31916     0/imm32/no-disp32
31917     0/imm32/no-xm32
31918     0/imm32/no-x32
31919     0x11/imm32/alloc-id:fake
31920     _Primitive-compare-reg-with-literal/imm32/next
31921 _Primitive-compare-reg-with-literal:  # (payload primitive)
31922     0x11/imm32/alloc-id:fake:payload
31923     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
31924     0x11/imm32/alloc-id:fake
31925     _string-compare/imm32/name
31926     0x11/imm32/alloc-id:fake
31927     Int-var-in-register-and-literal/imm32/inouts
31928     0/imm32/no-outputs
31929     0/imm32/no-outputs
31930     0x11/imm32/alloc-id:fake
31931     _string_81_subop_compare/imm32/subx-name
31932     1/imm32/rm32-is-first-inout
31933     0/imm32/no-r32
31934     2/imm32/imm32-is-second-inout
31935     0/imm32/no-imm8
31936     0/imm32/no-disp32
31937     0/imm32/no-xm32
31938     0/imm32/no-x32
31939     0x11/imm32/alloc-id:fake
31940     _Primitive-compare-mem-with-literal/imm32/next
31941 _Primitive-compare-mem-with-literal:  # (payload primitive)
31942     0x11/imm32/alloc-id:fake:payload
31943     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
31944     0x11/imm32/alloc-id:fake
31945     _string-compare/imm32/name
31946     0x11/imm32/alloc-id:fake
31947     Int-var-and-literal/imm32/inouts
31948     0/imm32/no-outputs
31949     0/imm32/no-outputs
31950     0x11/imm32/alloc-id:fake
31951     _string_81_subop_compare/imm32/subx-name
31952     1/imm32/rm32-is-first-inout
31953     0/imm32/no-r32
31954     2/imm32/imm32-is-second-inout
31955     0/imm32/no-imm8
31956     0/imm32/no-disp32
31957     0/imm32/no-xm32
31958     0/imm32/no-x32
31959     0x11/imm32/alloc-id:fake
31960     _Primitive-negate-reg/imm32/next
31961 # - negate
31962 _Primitive-negate-reg:  # (payload primitive)
31963     0x11/imm32/alloc-id:fake:payload
31964     # var1/reg <- negate => f7 3/subop/negate var1/rm32
31965     0x11/imm32/alloc-id:fake
31966     _string-negate/imm32/name
31967     0/imm32/no-inouts
31968     0/imm32/no-inouts
31969     0x11/imm32/alloc-id:fake
31970     Single-int-var-in-some-register/imm32/outputs
31971     0x11/imm32/alloc-id:fake
31972     _string_f7_subop_negate/imm32/subx-name
31973     3/imm32/rm32-is-first-output
31974     0/imm32/no-r32
31975     0/imm32/no-imm32
31976     0/imm32/no-imm8
31977     0/imm32/no-disp32
31978     0/imm32/no-xm32
31979     0/imm32/no-x32
31980     0x11/imm32/alloc-id:fake
31981     _Primitive-negate-mem/imm32/next
31982 _Primitive-negate-mem:  # (payload primitive)
31983     0x11/imm32/alloc-id:fake:payload
31984     # negate var1 => f7 3/subop/negate var1/rm32
31985     0x11/imm32/alloc-id:fake
31986     _string-negate/imm32/name
31987     0x11/imm32/alloc-id:fake
31988     Single-int-var-in-mem/imm32/inouts
31989     0/imm32/no-outputs
31990     0/imm32/no-outputs
31991     0x11/imm32/alloc-id:fake
31992     _string_f7_subop_negate/imm32/subx-name
31993     1/imm32/rm32-is-first-inout
31994     0/imm32/no-r32
31995     0/imm32/no-imm32
31996     0/imm32/no-imm8
31997     0/imm32/no-disp32
31998     0/imm32/no-xm32
31999     0/imm32/no-x32
32000     0x11/imm32/alloc-id:fake
32001     _Primitive-multiply-reg-by-reg/imm32/next
32002 # - multiply
32003 _Primitive-multiply-reg-by-reg:  # (payload primitive)
32004     0x11/imm32/alloc-id:fake:payload
32005     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
32006     0x11/imm32/alloc-id:fake
32007     _string-multiply/imm32/name
32008     0x11/imm32/alloc-id:fake
32009     Single-int-var-in-some-register/imm32/inouts
32010     0x11/imm32/alloc-id:fake
32011     Single-int-var-in-some-register/imm32/outputs
32012     0x11/imm32/alloc-id:fake
32013     _string_0f_af_multiply/imm32/subx-name
32014     1/imm32/rm32-is-first-inout
32015     3/imm32/r32-is-first-output
32016     0/imm32/no-imm32
32017     0/imm32/no-imm8
32018     0/imm32/no-disp32
32019     0/imm32/no-xm32
32020     0/imm32/no-x32
32021     0x11/imm32/alloc-id:fake
32022     _Primitive-multiply-reg-by-mem/imm32/next
32023 _Primitive-multiply-reg-by-mem:  # (payload primitive)
32024     0x11/imm32/alloc-id:fake:payload
32025     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
32026     0x11/imm32/alloc-id:fake
32027     _string-multiply/imm32/name
32028     0x11/imm32/alloc-id:fake
32029     Single-int-var-in-mem/imm32/inouts
32030     0x11/imm32/alloc-id:fake
32031     Single-int-var-in-some-register/imm32/outputs
32032     0x11/imm32/alloc-id:fake
32033     _string_0f_af_multiply/imm32/subx-name
32034     1/imm32/rm32-is-first-inout
32035     3/imm32/r32-is-first-output
32036     0/imm32/no-imm32
32037     0/imm32/no-imm8
32038     0/imm32/no-disp32
32039     0/imm32/no-xm32
32040     0/imm32/no-x32
32041     0x11/imm32/alloc-id:fake
32042     _Primitive-convert-mem-to-xreg/imm32/next
32043 # - convert int to floating point
32044 _Primitive-convert-mem-to-xreg:  # (payload primitive)
32045     0x11/imm32/alloc-id:fake:payload
32046     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
32047     0x11/imm32/alloc-id:fake
32048     _string-convert/imm32/name
32049     0x11/imm32/alloc-id:fake
32050     Single-int-var-in-mem/imm32/inouts
32051     0x11/imm32/alloc-id:fake
32052     Single-float-var-in-some-register/imm32/outputs
32053     0x11/imm32/alloc-id:fake
32054     _string_f3_0f_2a_convert_to_float/imm32/subx-name
32055     1/imm32/rm32-is-first-inout
32056     0/imm32/no-r32
32057     0/imm32/no-imm32
32058     0/imm32/no-imm8
32059     0/imm32/no-disp32
32060     0/imm32/no-xm32
32061     3/imm32/x32-is-first-output
32062     0x11/imm32/alloc-id:fake
32063     _Primitive-convert-reg-to-xreg/imm32/next
32064 _Primitive-convert-reg-to-xreg:  # (payload primitive)
32065     0x11/imm32/alloc-id:fake:payload
32066     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
32067     0x11/imm32/alloc-id:fake
32068     _string-convert/imm32/name
32069     0x11/imm32/alloc-id:fake
32070     Single-int-var-in-some-register/imm32/inouts
32071     0x11/imm32/alloc-id:fake
32072     Single-float-var-in-some-register/imm32/outputs
32073     0x11/imm32/alloc-id:fake
32074     _string_f3_0f_2a_convert_to_float/imm32/subx-name
32075     1/imm32/rm32-is-first-inout
32076     0/imm32/no-r32
32077     0/imm32/no-imm32
32078     0/imm32/no-imm8
32079     0/imm32/no-disp32
32080     0/imm32/no-xm32
32081     3/imm32/x32-is-first-output
32082     0x11/imm32/alloc-id:fake
32083     _Primitive-convert-xmem-to-reg/imm32/next
32084 # - convert floating point to int
32085 _Primitive-convert-xmem-to-reg:  # (payload primitive)
32086     0x11/imm32/alloc-id:fake:payload
32087     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
32088     0x11/imm32/alloc-id:fake
32089     _string-convert/imm32/name
32090     0x11/imm32/alloc-id:fake
32091     Single-float-var-in-mem/imm32/inouts
32092     0x11/imm32/alloc-id:fake
32093     Single-int-var-in-some-register/imm32/outputs
32094     0x11/imm32/alloc-id:fake
32095     _string_f3_0f_2d_convert_to_int/imm32/subx-name
32096     0/imm32/no-rm32
32097     3/imm32/r32-is-first-output
32098     0/imm32/no-imm32
32099     0/imm32/no-imm8
32100     0/imm32/no-disp32
32101     1/imm32/xm32-is-first-inout
32102     0/imm32/no-x32
32103     0x11/imm32/alloc-id:fake
32104     _Primitive-convert-xreg-to-reg/imm32/next
32105 _Primitive-convert-xreg-to-reg:  # (payload primitive)
32106     0x11/imm32/alloc-id:fake:payload
32107     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
32108     0x11/imm32/alloc-id:fake
32109     _string-convert/imm32/name
32110     0x11/imm32/alloc-id:fake
32111     Single-float-var-in-some-register/imm32/inouts
32112     0x11/imm32/alloc-id:fake
32113     Single-int-var-in-some-register/imm32/outputs
32114     0x11/imm32/alloc-id:fake
32115     _string_f3_0f_2d_convert_to_int/imm32/subx-name
32116     0/imm32/no-rm32
32117     3/imm32/r32-is-first-output
32118     0/imm32/no-imm32
32119     0/imm32/no-imm8
32120     0/imm32/no-disp32
32121     1/imm32/xm32-is-first-inout
32122     0/imm32/no-x32
32123     0x11/imm32/alloc-id:fake
32124     _Primitive-truncate-xmem-to-reg/imm32/next
32125 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
32126     0x11/imm32/alloc-id:fake:payload
32127     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
32128     0x11/imm32/alloc-id:fake
32129     _string-truncate/imm32/name
32130     0x11/imm32/alloc-id:fake
32131     Single-float-var-in-mem/imm32/inouts
32132     0x11/imm32/alloc-id:fake
32133     Single-int-var-in-some-register/imm32/outputs
32134     0x11/imm32/alloc-id:fake
32135     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
32136     0/imm32/no-rm32
32137     3/imm32/r32-is-first-output
32138     0/imm32/no-imm32
32139     0/imm32/no-imm8
32140     0/imm32/no-disp32
32141     1/imm32/xm32-is-first-inout
32142     0/imm32/no-x32
32143     0x11/imm32/alloc-id:fake
32144     _Primitive-truncate-xreg-to-reg/imm32/next
32145 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
32146     0x11/imm32/alloc-id:fake:payload
32147     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
32148     0x11/imm32/alloc-id:fake
32149     _string-truncate/imm32/name
32150     0x11/imm32/alloc-id:fake
32151     Single-float-var-in-some-register/imm32/inouts
32152     0x11/imm32/alloc-id:fake
32153     Single-int-var-in-some-register/imm32/outputs
32154     0x11/imm32/alloc-id:fake
32155     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
32156     0/imm32/no-rm32
32157     3/imm32/r32-is-first-output
32158     0/imm32/no-imm32
32159     0/imm32/no-imm8
32160     0/imm32/no-disp32
32161     1/imm32/xm32-is-first-inout
32162     0/imm32/no-x32
32163     0x11/imm32/alloc-id:fake
32164     _Primitive-reinterpret-xmem-as-reg/imm32/next
32165 # - reinterpret bytes (just for debugging)
32166 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
32167     0x11/imm32/alloc-id:fake:payload
32168     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
32169     0x11/imm32/alloc-id:fake
32170     _string-reinterpret/imm32/name
32171     0x11/imm32/alloc-id:fake
32172     Single-float-var-in-mem/imm32/inouts
32173     0x11/imm32/alloc-id:fake
32174     Single-int-var-in-some-register/imm32/outputs
32175     0x11/imm32/alloc-id:fake
32176     _string_8b_->/imm32/subx-name
32177     0/imm32/no-rm32
32178     3/imm32/r32-is-first-output
32179     0/imm32/no-imm32
32180     0/imm32/no-imm8
32181     0/imm32/no-disp32
32182     1/imm32/xm32-is-first-inout
32183     0/imm32/no-x32
32184     0x11/imm32/alloc-id:fake
32185     _Primitive-reinterpret-mem-as-xreg/imm32/next
32186 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
32187     0x11/imm32/alloc-id:fake:payload
32188     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
32189     0x11/imm32/alloc-id:fake
32190     _string-reinterpret/imm32/name
32191     0x11/imm32/alloc-id:fake
32192     Single-int-var-in-mem/imm32/inouts
32193     0x11/imm32/alloc-id:fake
32194     Single-float-var-in-some-register/imm32/outputs
32195     0x11/imm32/alloc-id:fake
32196     _string_f3_0f_10_copy/imm32/subx-name
32197     1/imm32/rm32-is-first-inout
32198     0/imm32/no-r32
32199     0/imm32/no-imm32
32200     0/imm32/no-imm8
32201     0/imm32/no-disp32
32202     0/imm32/no-xm32
32203     3/imm32/x32-is-first-output
32204     0x11/imm32/alloc-id:fake
32205     _Primitive-copy-xreg-to-xreg/imm32/next
32206 # - floating-point copy
32207 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
32208     0x11/imm32/alloc-id:fake:payload
32209     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
32210     0x11/imm32/alloc-id:fake
32211     _string-copy/imm32/name
32212     0x11/imm32/alloc-id:fake
32213     Single-float-var-in-some-register/imm32/inouts
32214     0x11/imm32/alloc-id:fake
32215     Single-float-var-in-some-register/imm32/outputs
32216     0x11/imm32/alloc-id:fake
32217     _string_f3_0f_11_copy/imm32/subx-name
32218     0/imm32/no-rm32
32219     0/imm32/no-r32
32220     0/imm32/no-imm32
32221     0/imm32/no-imm8
32222     0/imm32/no-disp32
32223     3/imm32/xm32-is-first-output
32224     1/imm32/x32-is-first-inout
32225     0x11/imm32/alloc-id:fake
32226     _Primitive-copy-xreg-to-mem/imm32/next
32227 _Primitive-copy-xreg-to-mem:  # (payload primitive)
32228     0x11/imm32/alloc-id:fake:payload
32229     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
32230     0x11/imm32/alloc-id:fake
32231     _string-copy-to/imm32/name
32232     0x11/imm32/alloc-id:fake
32233     Two-args-float-stack-float-reg/imm32/inouts
32234     0/imm32/no-outputs
32235     0/imm32/no-outputs
32236     0x11/imm32/alloc-id:fake
32237     _string_f3_0f_11_copy/imm32/subx-name
32238     0/imm32/no-rm32
32239     0/imm32/no-r32
32240     0/imm32/no-imm32
32241     0/imm32/no-imm8
32242     0/imm32/no-disp32
32243     1/imm32/xm32-is-first-inout
32244     2/imm32/x32-is-second-inout
32245     0x11/imm32/alloc-id:fake
32246     _Primitive-copy-mem-to-xreg/imm32/next
32247 _Primitive-copy-mem-to-xreg:  # (payload primitive)
32248     0x11/imm32/alloc-id:fake:payload
32249     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
32250     0x11/imm32/alloc-id:fake
32251     _string-copy/imm32/name
32252     0x11/imm32/alloc-id:fake
32253     Single-float-var-in-mem/imm32/inouts
32254     0x11/imm32/alloc-id:fake
32255     Single-float-var-in-some-register/imm32/outputs
32256     0x11/imm32/alloc-id:fake
32257     _string_f3_0f_10_copy/imm32/subx-name
32258     0/imm32/no-rm32
32259     0/imm32/no-r32
32260     0/imm32/no-imm32
32261     0/imm32/no-imm8
32262     0/imm32/no-disp32
32263     1/imm32/xm32-is-first-inout
32264     3/imm32/x32-is-first-output
32265     0x11/imm32/alloc-id:fake
32266     _Primitive-address-of-xmem/imm32/next
32267 # - floating-point-address
32268 _Primitive-address-of-xmem:  # (payload primitive)
32269     0x11/imm32/alloc-id:fake:payload
32270     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
32271     0x11/imm32/alloc-id:fake
32272     _string-address/imm32/name
32273     0x11/imm32/alloc-id:fake
32274     Single-float-var-in-mem/imm32/inouts
32275     0x11/imm32/alloc-id:fake
32276     Single-addr-var-in-some-register/imm32/outputs
32277     0x11/imm32/alloc-id:fake
32278     _string_8d_copy_address/imm32/subx-name
32279     1/imm32/rm32-is-first-inout
32280     3/imm32/r32-is-first-output
32281     0/imm32/no-imm32
32282     0/imm32/no-imm8
32283     0/imm32/no-disp32
32284     0/imm32/no-xm32
32285     0/imm32/no-x32
32286     0x11/imm32/alloc-id:fake
32287     _Primitive-add-xreg-to-xreg/imm32/next
32288 # - floating-point add
32289 _Primitive-add-xreg-to-xreg:  # (payload primitive)
32290     0x11/imm32/alloc-id:fake:payload
32291     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
32292     0x11/imm32/alloc-id:fake
32293     _string-add/imm32/name
32294     0x11/imm32/alloc-id:fake
32295     Single-float-var-in-some-register/imm32/inouts
32296     0x11/imm32/alloc-id:fake
32297     Single-float-var-in-some-register/imm32/outputs
32298     0x11/imm32/alloc-id:fake
32299     _string_f3_0f_58_add/imm32/subx-name
32300     0/imm32/no-rm32
32301     0/imm32/no-r32
32302     0/imm32/no-imm32
32303     0/imm32/no-imm8
32304     0/imm32/no-disp32
32305     1/imm32/xm32-is-first-inout
32306     3/imm32/x32-is-first-output
32307     0x11/imm32/alloc-id:fake
32308     _Primitive-add-mem-to-xreg/imm32/next
32309 _Primitive-add-mem-to-xreg:  # (payload primitive)
32310     0x11/imm32/alloc-id:fake:payload
32311     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
32312     0x11/imm32/alloc-id:fake
32313     _string-add/imm32/name
32314     0x11/imm32/alloc-id:fake
32315     Single-float-var-in-mem/imm32/inouts
32316     0x11/imm32/alloc-id:fake
32317     Single-float-var-in-some-register/imm32/outputs
32318     0x11/imm32/alloc-id:fake
32319     _string_f3_0f_58_add/imm32/subx-name
32320     0/imm32/no-rm32
32321     0/imm32/no-r32
32322     0/imm32/no-imm32
32323     0/imm32/no-imm8
32324     0/imm32/no-disp32
32325     1/imm32/xm32-is-first-inout
32326     3/imm32/x32-is-first-output
32327     0x11/imm32/alloc-id:fake
32328     _Primitive-subtract-xreg-from-xreg/imm32/next
32329 # - floating-point subtract
32330 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
32331     0x11/imm32/alloc-id:fake:payload
32332     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
32333     0x11/imm32/alloc-id:fake
32334     _string-subtract/imm32/name
32335     0x11/imm32/alloc-id:fake
32336     Single-float-var-in-some-register/imm32/inouts
32337     0x11/imm32/alloc-id:fake
32338     Single-float-var-in-some-register/imm32/outputs
32339     0x11/imm32/alloc-id:fake
32340     _string_f3_0f_5c_subtract/imm32/subx-name
32341     0/imm32/no-rm32
32342     0/imm32/no-r32
32343     0/imm32/no-imm32
32344     0/imm32/no-imm8
32345     0/imm32/no-disp32
32346     1/imm32/xm32-is-first-inout
32347     3/imm32/x32-is-first-output
32348     0x11/imm32/alloc-id:fake
32349     _Primitive-subtract-mem-from-xreg/imm32/next
32350 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
32351     0x11/imm32/alloc-id:fake:payload
32352     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
32353     0x11/imm32/alloc-id:fake
32354     _string-subtract/imm32/name
32355     0x11/imm32/alloc-id:fake
32356     Single-float-var-in-mem/imm32/inouts
32357     0x11/imm32/alloc-id:fake
32358     Single-float-var-in-some-register/imm32/outputs
32359     0x11/imm32/alloc-id:fake
32360     _string_f3_0f_5c_subtract/imm32/subx-name
32361     0/imm32/no-rm32
32362     0/imm32/no-r32
32363     0/imm32/no-imm32
32364     0/imm32/no-imm8
32365     0/imm32/no-disp32
32366     1/imm32/xm32-is-first-inout
32367     3/imm32/x32-is-first-output
32368     0x11/imm32/alloc-id:fake
32369     _Primitive-multiply-xreg-by-xreg/imm32/next
32370 # - floating-point multiply
32371 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
32372     0x11/imm32/alloc-id:fake:payload
32373     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
32374     0x11/imm32/alloc-id:fake
32375     _string-multiply/imm32/name
32376     0x11/imm32/alloc-id:fake
32377     Single-float-var-in-some-register/imm32/inouts
32378     0x11/imm32/alloc-id:fake
32379     Single-float-var-in-some-register/imm32/outputs
32380     0x11/imm32/alloc-id:fake
32381     _string_f3_0f_59_multiply/imm32/subx-name
32382     0/imm32/no-rm32
32383     0/imm32/no-r32
32384     0/imm32/no-imm32
32385     0/imm32/no-imm8
32386     0/imm32/no-disp32
32387     1/imm32/xm32-is-first-inout
32388     3/imm32/x32-is-first-output
32389     0x11/imm32/alloc-id:fake
32390     _Primitive-multiply-xreg-by-mem/imm32/next
32391 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
32392     0x11/imm32/alloc-id:fake:payload
32393     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
32394     0x11/imm32/alloc-id:fake
32395     _string-multiply/imm32/name
32396     0x11/imm32/alloc-id:fake
32397     Single-float-var-in-mem/imm32/inouts
32398     0x11/imm32/alloc-id:fake
32399     Single-float-var-in-some-register/imm32/outputs
32400     0x11/imm32/alloc-id:fake
32401     _string_f3_0f_59_multiply/imm32/subx-name
32402     0/imm32/no-rm32
32403     0/imm32/no-r32
32404     0/imm32/no-imm32
32405     0/imm32/no-imm8
32406     0/imm32/no-disp32
32407     1/imm32/xm32-is-first-inout
32408     3/imm32/x32-is-first-output
32409     0x11/imm32/alloc-id:fake
32410     _Primitive-divide-xreg-by-xreg/imm32/next
32411 # - floating-point divide
32412 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
32413     0x11/imm32/alloc-id:fake:payload
32414     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32415     0x11/imm32/alloc-id:fake
32416     _string-divide/imm32/name
32417     0x11/imm32/alloc-id:fake
32418     Single-float-var-in-some-register/imm32/inouts
32419     0x11/imm32/alloc-id:fake
32420     Single-float-var-in-some-register/imm32/outputs
32421     0x11/imm32/alloc-id:fake
32422     _string_f3_0f_5e_divide/imm32/subx-name
32423     0/imm32/no-rm32
32424     0/imm32/no-r32
32425     0/imm32/no-imm32
32426     0/imm32/no-imm8
32427     0/imm32/no-disp32
32428     1/imm32/xm32-is-first-inout
32429     3/imm32/x32-is-first-output
32430     0x11/imm32/alloc-id:fake
32431     _Primitive-divide-xreg-by-mem/imm32/next
32432 _Primitive-divide-xreg-by-mem:  # (payload primitive)
32433     0x11/imm32/alloc-id:fake:payload
32434     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
32435     0x11/imm32/alloc-id:fake
32436     _string-divide/imm32/name
32437     0x11/imm32/alloc-id:fake
32438     Single-float-var-in-mem/imm32/inouts
32439     0x11/imm32/alloc-id:fake
32440     Single-float-var-in-some-register/imm32/outputs
32441     0x11/imm32/alloc-id:fake
32442     _string_f3_0f_5e_divide/imm32/subx-name
32443     0/imm32/no-rm32
32444     0/imm32/no-r32
32445     0/imm32/no-imm32
32446     0/imm32/no-imm8
32447     0/imm32/no-disp32
32448     1/imm32/xm32-is-first-inout
32449     3/imm32/x32-is-first-output
32450     0x11/imm32/alloc-id:fake
32451     _Primitive-max-xreg-with-xreg/imm32/next
32452 # - floating-point maximum
32453 _Primitive-max-xreg-with-xreg:  # (payload primitive)
32454     0x11/imm32/alloc-id:fake:payload
32455     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
32456     0x11/imm32/alloc-id:fake
32457     _string-max/imm32/name
32458     0x11/imm32/alloc-id:fake
32459     Single-float-var-in-some-register/imm32/inouts
32460     0x11/imm32/alloc-id:fake
32461     Single-float-var-in-some-register/imm32/outputs
32462     0x11/imm32/alloc-id:fake
32463     _string_f3_0f_5f_max/imm32/subx-name
32464     0/imm32/no-rm32
32465     0/imm32/no-r32
32466     0/imm32/no-imm32
32467     0/imm32/no-imm8
32468     0/imm32/no-disp32
32469     1/imm32/xm32-is-first-inout
32470     3/imm32/x32-is-first-output
32471     0x11/imm32/alloc-id:fake
32472     _Primitive-max-xreg-with-mem/imm32/next
32473 _Primitive-max-xreg-with-mem:  # (payload primitive)
32474     0x11/imm32/alloc-id:fake:payload
32475     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
32476     0x11/imm32/alloc-id:fake
32477     _string-max/imm32/name
32478     0x11/imm32/alloc-id:fake
32479     Single-float-var-in-mem/imm32/inouts
32480     0x11/imm32/alloc-id:fake
32481     Single-float-var-in-some-register/imm32/outputs
32482     0x11/imm32/alloc-id:fake
32483     _string_f3_0f_5f_max/imm32/subx-name
32484     0/imm32/no-rm32
32485     0/imm32/no-r32
32486     0/imm32/no-imm32
32487     0/imm32/no-imm8
32488     0/imm32/no-disp32
32489     1/imm32/xm32-is-first-inout
32490     3/imm32/x32-is-first-output
32491     0x11/imm32/alloc-id:fake
32492     _Primitive-min-xreg-with-xreg/imm32/next
32493 # - floating-point minimum
32494 _Primitive-min-xreg-with-xreg:  # (payload primitive)
32495     0x11/imm32/alloc-id:fake:payload
32496     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32497     0x11/imm32/alloc-id:fake
32498     _string-min/imm32/name
32499     0x11/imm32/alloc-id:fake
32500     Single-float-var-in-some-register/imm32/inouts
32501     0x11/imm32/alloc-id:fake
32502     Single-float-var-in-some-register/imm32/outputs
32503     0x11/imm32/alloc-id:fake
32504     _string_f3_0f_5d_min/imm32/subx-name
32505     0/imm32/no-rm32
32506     0/imm32/no-r32
32507     0/imm32/no-imm32
32508     0/imm32/no-imm8
32509     0/imm32/no-disp32
32510     1/imm32/xm32-is-first-inout
32511     3/imm32/x32-is-first-output
32512     0x11/imm32/alloc-id:fake
32513     _Primitive-min-xreg-with-mem/imm32/next
32514 _Primitive-min-xreg-with-mem:  # (payload primitive)
32515     0x11/imm32/alloc-id:fake:payload
32516     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
32517     0x11/imm32/alloc-id:fake
32518     _string-min/imm32/name
32519     0x11/imm32/alloc-id:fake
32520     Single-float-var-in-mem/imm32/inouts
32521     0x11/imm32/alloc-id:fake
32522     Single-float-var-in-some-register/imm32/outputs
32523     0x11/imm32/alloc-id:fake
32524     _string_f3_0f_5d_min/imm32/subx-name
32525     0/imm32/no-rm32
32526     0/imm32/no-r32
32527     0/imm32/no-imm32
32528     0/imm32/no-imm8
32529     0/imm32/no-disp32
32530     1/imm32/xm32-is-first-inout
32531     3/imm32/x32-is-first-output
32532     0x11/imm32/alloc-id:fake
32533     _Primitive-reciprocal-xreg-to-xreg/imm32/next
32534 # - floating-point reciprocal
32535 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
32536     0x11/imm32/alloc-id:fake:payload
32537     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32538     0x11/imm32/alloc-id:fake
32539     _string-reciprocal/imm32/name
32540     0x11/imm32/alloc-id:fake
32541     Single-float-var-in-some-register/imm32/inouts
32542     0x11/imm32/alloc-id:fake
32543     Single-float-var-in-some-register/imm32/outputs
32544     0x11/imm32/alloc-id:fake
32545     _string_f3_0f_53_reciprocal/imm32/subx-name
32546     0/imm32/no-rm32
32547     0/imm32/no-r32
32548     0/imm32/no-imm32
32549     0/imm32/no-imm8
32550     0/imm32/no-disp32
32551     1/imm32/xm32-is-first-inout
32552     3/imm32/x32-is-first-output
32553     0x11/imm32/alloc-id:fake
32554     _Primitive-reciprocal-mem-to-xreg/imm32/next
32555 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
32556     0x11/imm32/alloc-id:fake:payload
32557     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
32558     0x11/imm32/alloc-id:fake
32559     _string-reciprocal/imm32/name
32560     0x11/imm32/alloc-id:fake
32561     Single-float-var-in-mem/imm32/inouts
32562     0x11/imm32/alloc-id:fake
32563     Single-float-var-in-some-register/imm32/outputs
32564     0x11/imm32/alloc-id:fake
32565     _string_f3_0f_53_reciprocal/imm32/subx-name
32566     0/imm32/no-rm32
32567     0/imm32/no-r32
32568     0/imm32/no-imm32
32569     0/imm32/no-imm8
32570     0/imm32/no-disp32
32571     1/imm32/xm32-is-first-inout
32572     3/imm32/x32-is-first-output
32573     0x11/imm32/alloc-id:fake
32574     _Primitive-square-root-xreg-to-xreg/imm32/next
32575 # - floating-point square root
32576 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
32577     0x11/imm32/alloc-id:fake:payload
32578     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
32579     0x11/imm32/alloc-id:fake
32580     _string-square-root/imm32/name
32581     0x11/imm32/alloc-id:fake
32582     Single-float-var-in-some-register/imm32/inouts
32583     0x11/imm32/alloc-id:fake
32584     Single-float-var-in-some-register/imm32/outputs
32585     0x11/imm32/alloc-id:fake
32586     _string_f3_0f_51_square_root/imm32/subx-name
32587     0/imm32/no-rm32
32588     0/imm32/no-r32
32589     0/imm32/no-imm32
32590     0/imm32/no-imm8
32591     0/imm32/no-disp32
32592     1/imm32/xm32-is-first-inout
32593     3/imm32/x32-is-first-output
32594     0x11/imm32/alloc-id:fake
32595     _Primitive-square-root-mem-to-xreg/imm32/next
32596 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
32597     0x11/imm32/alloc-id:fake:payload
32598     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
32599     0x11/imm32/alloc-id:fake
32600     _string-square-root/imm32/name
32601     0x11/imm32/alloc-id:fake
32602     Single-float-var-in-mem/imm32/inouts
32603     0x11/imm32/alloc-id:fake
32604     Single-float-var-in-some-register/imm32/outputs
32605     0x11/imm32/alloc-id:fake
32606     _string_f3_0f_51_square_root/imm32/subx-name
32607     0/imm32/no-rm32
32608     0/imm32/no-r32
32609     0/imm32/no-imm32
32610     0/imm32/no-imm8
32611     0/imm32/no-disp32
32612     1/imm32/xm32-is-first-inout
32613     3/imm32/x32-is-first-output
32614     0x11/imm32/alloc-id:fake
32615     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
32616 # - floating-point inverse square root 1/sqrt(x)
32617 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
32618     0x11/imm32/alloc-id:fake:payload
32619     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32620     0x11/imm32/alloc-id:fake
32621     _string-inverse-square-root/imm32/name
32622     0x11/imm32/alloc-id:fake
32623     Single-float-var-in-some-register/imm32/inouts
32624     0x11/imm32/alloc-id:fake
32625     Single-float-var-in-some-register/imm32/outputs
32626     0x11/imm32/alloc-id:fake
32627     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32628     0/imm32/no-rm32
32629     0/imm32/no-r32
32630     0/imm32/no-imm32
32631     0/imm32/no-imm8
32632     0/imm32/no-disp32
32633     1/imm32/xm32-is-first-inout
32634     3/imm32/x32-is-first-output
32635     0x11/imm32/alloc-id:fake
32636     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
32637 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
32638     0x11/imm32/alloc-id:fake:payload
32639     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
32640     0x11/imm32/alloc-id:fake
32641     _string-inverse-square-root/imm32/name
32642     0x11/imm32/alloc-id:fake
32643     Single-float-var-in-mem/imm32/inouts
32644     0x11/imm32/alloc-id:fake
32645     Single-float-var-in-some-register/imm32/outputs
32646     0x11/imm32/alloc-id:fake
32647     _string_f3_0f_52_inverse_square_root/imm32/subx-name
32648     0/imm32/no-rm32
32649     0/imm32/no-r32
32650     0/imm32/no-imm32
32651     0/imm32/no-imm8
32652     0/imm32/no-disp32
32653     1/imm32/xm32-is-first-inout
32654     3/imm32/x32-is-first-output
32655     0x11/imm32/alloc-id:fake
32656     _Primitive-compare-xreg-with-xreg/imm32/next
32657 # - floating-point compare
32658 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
32659     0x11/imm32/alloc-id:fake:payload
32660     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
32661     0x11/imm32/alloc-id:fake
32662     _string-compare/imm32/name
32663     0x11/imm32/alloc-id:fake
32664     Two-float-args-in-regs/imm32/inouts
32665     0/imm32/no-outputs
32666     0/imm32/no-outputs
32667     0x11/imm32/alloc-id:fake
32668     _string_0f_2f_compare/imm32/subx-name
32669     0/imm32/no-rm32
32670     0/imm32/no-r32
32671     0/imm32/no-imm32
32672     0/imm32/no-imm8
32673     0/imm32/no-disp32
32674     2/imm32/xm32-is-second-inout
32675     1/imm32/x32-is-first-inout
32676     0x11/imm32/alloc-id:fake
32677     _Primitive-compare-xreg-with-mem/imm32/next
32678 _Primitive-compare-xreg-with-mem:  # (payload primitive)
32679     0x11/imm32/alloc-id:fake:payload
32680     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
32681     0x11/imm32/alloc-id:fake
32682     _string-compare/imm32/name
32683     0x11/imm32/alloc-id:fake
32684     Two-args-float-reg-float-stack/imm32/inouts
32685     0/imm32/no-outputs
32686     0/imm32/no-outputs
32687     0x11/imm32/alloc-id:fake
32688     _string_0f_2f_compare/imm32/subx-name
32689     0/imm32/no-rm32
32690     0/imm32/no-r32
32691     0/imm32/no-imm32
32692     0/imm32/no-imm8
32693     0/imm32/no-disp32
32694     2/imm32/xm32-is-second-inout
32695     1/imm32/x32-is-first-inout
32696     0x11/imm32/alloc-id:fake
32697     _Primitive-break-if-addr</imm32/next
32698 # - branches
32699 _Primitive-break-if-addr<:  # (payload primitive)
32700     0x11/imm32/alloc-id:fake:payload
32701     0x11/imm32/alloc-id:fake
32702     _string-break-if-addr</imm32/name
32703     0/imm32/no-inouts
32704     0/imm32/no-inouts
32705     0/imm32/no-outputs
32706     0/imm32/no-outputs
32707     0x11/imm32/alloc-id:fake
32708     _string_0f_82_jump_break/imm32/subx-name
32709     0/imm32/no-rm32
32710     0/imm32/no-r32
32711     0/imm32/no-imm32
32712     0/imm32/no-imm8
32713     0/imm32/no-disp32
32714     0/imm32/no-xm32
32715     0/imm32/no-x32
32716     0x11/imm32/alloc-id:fake
32717     _Primitive-break-if-addr>=/imm32/next
32718 _Primitive-break-if-addr>=:  # (payload primitive)
32719     0x11/imm32/alloc-id:fake:payload
32720     0x11/imm32/alloc-id:fake
32721     _string-break-if-addr>=/imm32/name
32722     0/imm32/no-inouts
32723     0/imm32/no-inouts
32724     0/imm32/no-outputs
32725     0/imm32/no-outputs
32726     0x11/imm32/alloc-id:fake
32727     _string_0f_83_jump_break/imm32/subx-name
32728     0/imm32/no-rm32
32729     0/imm32/no-r32
32730     0/imm32/no-imm32
32731     0/imm32/no-imm8
32732     0/imm32/no-disp32
32733     0/imm32/no-xm32
32734     0/imm32/no-x32
32735     0x11/imm32/alloc-id:fake
32736     _Primitive-break-if-=/imm32/next
32737 _Primitive-break-if-=:  # (payload primitive)
32738     0x11/imm32/alloc-id:fake:payload
32739     0x11/imm32/alloc-id:fake
32740     _string-break-if-=/imm32/name
32741     0/imm32/no-inouts
32742     0/imm32/no-inouts
32743     0/imm32/no-outputs
32744     0/imm32/no-outputs
32745     0x11/imm32/alloc-id:fake
32746     _string_0f_84_jump_break/imm32/subx-name
32747     0/imm32/no-rm32
32748     0/imm32/no-r32
32749     0/imm32/no-imm32
32750     0/imm32/no-imm8
32751     0/imm32/no-disp32
32752     0/imm32/no-xm32
32753     0/imm32/no-x32
32754     0x11/imm32/alloc-id:fake
32755     _Primitive-break-if-!=/imm32/next
32756 _Primitive-break-if-!=:  # (payload primitive)
32757     0x11/imm32/alloc-id:fake:payload
32758     0x11/imm32/alloc-id:fake
32759     _string-break-if-!=/imm32/name
32760     0/imm32/no-inouts
32761     0/imm32/no-inouts
32762     0/imm32/no-outputs
32763     0/imm32/no-outputs
32764     0x11/imm32/alloc-id:fake
32765     _string_0f_85_jump_break/imm32/subx-name
32766     0/imm32/no-rm32
32767     0/imm32/no-r32
32768     0/imm32/no-imm32
32769     0/imm32/no-imm8
32770     0/imm32/no-disp32
32771     0/imm32/no-xm32
32772     0/imm32/no-x32
32773     0x11/imm32/alloc-id:fake
32774     _Primitive-break-if-addr<=/imm32/next
32775 _Primitive-break-if-addr<=:  # (payload primitive)
32776     0x11/imm32/alloc-id:fake:payload
32777     0x11/imm32/alloc-id:fake
32778     _string-break-if-addr<=/imm32/name
32779     0/imm32/no-inouts
32780     0/imm32/no-inouts
32781     0/imm32/no-outputs
32782     0/imm32/no-outputs
32783     0x11/imm32/alloc-id:fake
32784     _string_0f_86_jump_break/imm32/subx-name
32785     0/imm32/no-rm32
32786     0/imm32/no-r32
32787     0/imm32/no-imm32
32788     0/imm32/no-imm8
32789     0/imm32/no-disp32
32790     0/imm32/no-xm32
32791     0/imm32/no-x32
32792     0x11/imm32/alloc-id:fake
32793     _Primitive-break-if-addr>/imm32/next
32794 _Primitive-break-if-addr>:  # (payload primitive)
32795     0x11/imm32/alloc-id:fake:payload
32796     0x11/imm32/alloc-id:fake
32797     _string-break-if-addr>/imm32/name
32798     0/imm32/no-inouts
32799     0/imm32/no-inouts
32800     0/imm32/no-outputs
32801     0/imm32/no-outputs
32802     0x11/imm32/alloc-id:fake
32803     _string_0f_87_jump_break/imm32/subx-name
32804     0/imm32/no-rm32
32805     0/imm32/no-r32
32806     0/imm32/no-imm32
32807     0/imm32/no-imm8
32808     0/imm32/no-disp32
32809     0/imm32/no-xm32
32810     0/imm32/no-x32
32811     0x11/imm32/alloc-id:fake
32812     _Primitive-break-if-</imm32/next
32813 _Primitive-break-if-<:  # (payload primitive)
32814     0x11/imm32/alloc-id:fake:payload
32815     0x11/imm32/alloc-id:fake
32816     _string-break-if-</imm32/name
32817     0/imm32/no-inouts
32818     0/imm32/no-inouts
32819     0/imm32/no-outputs
32820     0/imm32/no-outputs
32821     0x11/imm32/alloc-id:fake
32822     _string_0f_8c_jump_break/imm32/subx-name
32823     0/imm32/no-rm32
32824     0/imm32/no-r32
32825     0/imm32/no-imm32
32826     0/imm32/no-imm8
32827     0/imm32/no-disp32
32828     0/imm32/no-xm32
32829     0/imm32/no-x32
32830     0x11/imm32/alloc-id:fake
32831     _Primitive-break-if->=/imm32/next
32832 _Primitive-break-if->=:  # (payload primitive)
32833     0x11/imm32/alloc-id:fake:payload
32834     0x11/imm32/alloc-id:fake
32835     _string-break-if->=/imm32/name
32836     0/imm32/no-inouts
32837     0/imm32/no-inouts
32838     0/imm32/no-outputs
32839     0/imm32/no-outputs
32840     0x11/imm32/alloc-id:fake
32841     _string_0f_8d_jump_break/imm32/subx-name
32842     0/imm32/no-rm32
32843     0/imm32/no-r32
32844     0/imm32/no-imm32
32845     0/imm32/no-imm8
32846     0/imm32/no-disp32
32847     0/imm32/no-xm32
32848     0/imm32/no-x32
32849     0x11/imm32/alloc-id:fake
32850     _Primitive-break-if-<=/imm32/next
32851 _Primitive-break-if-<=:  # (payload primitive)
32852     0x11/imm32/alloc-id:fake:payload
32853     0x11/imm32/alloc-id:fake
32854     _string-break-if-<=/imm32/name
32855     0/imm32/no-inouts
32856     0/imm32/no-inouts
32857     0/imm32/no-outputs
32858     0/imm32/no-outputs
32859     0x11/imm32/alloc-id:fake
32860     _string_0f_8e_jump_break/imm32/subx-name
32861     0/imm32/no-rm32
32862     0/imm32/no-r32
32863     0/imm32/no-imm32
32864     0/imm32/no-imm8
32865     0/imm32/no-disp32
32866     0/imm32/no-xm32
32867     0/imm32/no-x32
32868     0x11/imm32/alloc-id:fake
32869     _Primitive-break-if->/imm32/next
32870 _Primitive-break-if->:  # (payload primitive)
32871     0x11/imm32/alloc-id:fake:payload
32872     0x11/imm32/alloc-id:fake
32873     _string-break-if->/imm32/name
32874     0/imm32/no-inouts
32875     0/imm32/no-inouts
32876     0/imm32/no-outputs
32877     0/imm32/no-outputs
32878     0x11/imm32/alloc-id:fake
32879     _string_0f_8f_jump_break/imm32/subx-name
32880     0/imm32/no-rm32
32881     0/imm32/no-r32
32882     0/imm32/no-imm32
32883     0/imm32/no-imm8
32884     0/imm32/no-disp32
32885     0/imm32/no-xm32
32886     0/imm32/no-x32
32887     0x11/imm32/alloc-id:fake
32888     _Primitive-break-if-carry/imm32/next
32889 _Primitive-break-if-carry:  # (payload primitive)
32890     0x11/imm32/alloc-id:fake:payload
32891     0x11/imm32/alloc-id:fake
32892     _string-break-if-carry/imm32/name
32893     0/imm32/no-inouts
32894     0/imm32/no-inouts
32895     0/imm32/no-outputs
32896     0/imm32/no-outputs
32897     0x11/imm32/alloc-id:fake
32898     _string_0f_82_jump_break/imm32/subx-name
32899     0/imm32/no-rm32
32900     0/imm32/no-r32
32901     0/imm32/no-imm32
32902     0/imm32/no-imm8
32903     0/imm32/no-disp32
32904     0/imm32/no-xm32
32905     0/imm32/no-x32
32906     0x11/imm32/alloc-id:fake
32907     _Primitive-break-if-not-carry/imm32/next
32908 _Primitive-break-if-not-carry:  # (payload primitive)
32909     0x11/imm32/alloc-id:fake:payload
32910     0x11/imm32/alloc-id:fake
32911     _string-break-if-not-carry/imm32/name
32912     0/imm32/no-inouts
32913     0/imm32/no-inouts
32914     0/imm32/no-outputs
32915     0/imm32/no-outputs
32916     0x11/imm32/alloc-id:fake
32917     _string_0f_83_jump_break/imm32/subx-name
32918     0/imm32/no-rm32
32919     0/imm32/no-r32
32920     0/imm32/no-imm32
32921     0/imm32/no-imm8
32922     0/imm32/no-disp32
32923     0/imm32/no-xm32
32924     0/imm32/no-x32
32925     0x11/imm32/alloc-id:fake
32926     _Primitive-break-if-overflow/imm32/next
32927 _Primitive-break-if-overflow:  # (payload primitive)
32928     0x11/imm32/alloc-id:fake:payload
32929     0x11/imm32/alloc-id:fake
32930     _string-break-if-overflow/imm32/name
32931     0/imm32/no-inouts
32932     0/imm32/no-inouts
32933     0/imm32/no-outputs
32934     0/imm32/no-outputs
32935     0x11/imm32/alloc-id:fake
32936     _string_0f_80_jump_break/imm32/subx-name
32937     0/imm32/no-rm32
32938     0/imm32/no-r32
32939     0/imm32/no-imm32
32940     0/imm32/no-imm8
32941     0/imm32/no-disp32
32942     0/imm32/no-xm32
32943     0/imm32/no-x32
32944     0x11/imm32/alloc-id:fake
32945     _Primitive-break-if-not-overflow/imm32/next
32946 _Primitive-break-if-not-overflow:  # (payload primitive)
32947     0x11/imm32/alloc-id:fake:payload
32948     0x11/imm32/alloc-id:fake
32949     _string-break-if-not-overflow/imm32/name
32950     0/imm32/no-inouts
32951     0/imm32/no-inouts
32952     0/imm32/no-outputs
32953     0/imm32/no-outputs
32954     0x11/imm32/alloc-id:fake
32955     _string_0f_81_jump_break/imm32/subx-name
32956     0/imm32/no-rm32
32957     0/imm32/no-r32
32958     0/imm32/no-imm32
32959     0/imm32/no-imm8
32960     0/imm32/no-disp32
32961     0/imm32/no-xm32
32962     0/imm32/no-x32
32963     0x11/imm32/alloc-id:fake
32964     _Primitive-break/imm32/next
32965 _Primitive-break:  # (payload primitive)
32966     0x11/imm32/alloc-id:fake:payload
32967     0x11/imm32/alloc-id:fake
32968     _string-break/imm32/name
32969     0/imm32/no-inouts
32970     0/imm32/no-inouts
32971     0/imm32/no-outputs
32972     0/imm32/no-outputs
32973     0x11/imm32/alloc-id:fake
32974     _string_e9_jump_break/imm32/subx-name
32975     0/imm32/no-rm32
32976     0/imm32/no-r32
32977     0/imm32/no-imm32
32978     0/imm32/no-imm8
32979     0/imm32/no-disp32
32980     0/imm32/no-xm32
32981     0/imm32/no-x32
32982     0x11/imm32/alloc-id:fake
32983     _Primitive-loop-if-addr</imm32/next
32984 _Primitive-loop-if-addr<:  # (payload primitive)
32985     0x11/imm32/alloc-id:fake:payload
32986     0x11/imm32/alloc-id:fake
32987     _string-loop-if-addr</imm32/name
32988     0/imm32/no-inouts
32989     0/imm32/no-inouts
32990     0/imm32/no-outputs
32991     0/imm32/no-outputs
32992     0x11/imm32/alloc-id:fake
32993     _string_0f_82_jump_loop/imm32/subx-name
32994     0/imm32/no-rm32
32995     0/imm32/no-r32
32996     0/imm32/no-imm32
32997     0/imm32/no-imm8
32998     0/imm32/no-disp32
32999     0/imm32/no-xm32
33000     0/imm32/no-x32
33001     0x11/imm32/alloc-id:fake
33002     _Primitive-loop-if-addr>=/imm32/next
33003 _Primitive-loop-if-addr>=:  # (payload primitive)
33004     0x11/imm32/alloc-id:fake:payload
33005     0x11/imm32/alloc-id:fake
33006     _string-loop-if-addr>=/imm32/name
33007     0/imm32/no-inouts
33008     0/imm32/no-inouts
33009     0/imm32/no-outputs
33010     0/imm32/no-outputs
33011     0x11/imm32/alloc-id:fake
33012     _string_0f_83_jump_loop/imm32/subx-name
33013     0/imm32/no-rm32
33014     0/imm32/no-r32
33015     0/imm32/no-imm32
33016     0/imm32/no-imm8
33017     0/imm32/no-disp32
33018     0/imm32/no-xm32
33019     0/imm32/no-x32
33020     0x11/imm32/alloc-id:fake
33021     _Primitive-loop-if-=/imm32/next
33022 _Primitive-loop-if-=:  # (payload primitive)
33023     0x11/imm32/alloc-id:fake:payload
33024     0x11/imm32/alloc-id:fake
33025     _string-loop-if-=/imm32/name
33026     0/imm32/no-inouts
33027     0/imm32/no-inouts
33028     0/imm32/no-outputs
33029     0/imm32/no-outputs
33030     0x11/imm32/alloc-id:fake
33031     _string_0f_84_jump_loop/imm32/subx-name
33032     0/imm32/no-rm32
33033     0/imm32/no-r32
33034     0/imm32/no-imm32
33035     0/imm32/no-imm8
33036     0/imm32/no-disp32
33037     0/imm32/no-xm32
33038     0/imm32/no-x32
33039     0x11/imm32/alloc-id:fake
33040     _Primitive-loop-if-!=/imm32/next
33041 _Primitive-loop-if-!=:  # (payload primitive)
33042     0x11/imm32/alloc-id:fake:payload
33043     0x11/imm32/alloc-id:fake
33044     _string-loop-if-!=/imm32/name
33045     0/imm32/no-inouts
33046     0/imm32/no-inouts
33047     0/imm32/no-outputs
33048     0/imm32/no-outputs
33049     0x11/imm32/alloc-id:fake
33050     _string_0f_85_jump_loop/imm32/subx-name
33051     0/imm32/no-rm32
33052     0/imm32/no-r32
33053     0/imm32/no-imm32
33054     0/imm32/no-imm8
33055     0/imm32/no-disp32
33056     0/imm32/no-xm32
33057     0/imm32/no-x32
33058     0x11/imm32/alloc-id:fake
33059     _Primitive-loop-if-addr<=/imm32/next
33060 _Primitive-loop-if-addr<=:  # (payload primitive)
33061     0x11/imm32/alloc-id:fake:payload
33062     0x11/imm32/alloc-id:fake
33063     _string-loop-if-addr<=/imm32/name
33064     0/imm32/no-inouts
33065     0/imm32/no-inouts
33066     0/imm32/no-outputs
33067     0/imm32/no-outputs
33068     0x11/imm32/alloc-id:fake
33069     _string_0f_86_jump_loop/imm32/subx-name
33070     0/imm32/no-rm32
33071     0/imm32/no-r32
33072     0/imm32/no-imm32
33073     0/imm32/no-imm8
33074     0/imm32/no-disp32
33075     0/imm32/no-xm32
33076     0/imm32/no-x32
33077     0x11/imm32/alloc-id:fake
33078     _Primitive-loop-if-addr>/imm32/next
33079 _Primitive-loop-if-addr>:  # (payload primitive)
33080     0x11/imm32/alloc-id:fake:payload
33081     0x11/imm32/alloc-id:fake
33082     _string-loop-if-addr>/imm32/name
33083     0/imm32/no-inouts
33084     0/imm32/no-inouts
33085     0/imm32/no-outputs
33086     0/imm32/no-outputs
33087     0x11/imm32/alloc-id:fake
33088     _string_0f_87_jump_loop/imm32/subx-name
33089     0/imm32/no-rm32
33090     0/imm32/no-r32
33091     0/imm32/no-imm32
33092     0/imm32/no-imm8
33093     0/imm32/no-disp32
33094     0/imm32/no-xm32
33095     0/imm32/no-x32
33096     0x11/imm32/alloc-id:fake
33097     _Primitive-loop-if-</imm32/next
33098 _Primitive-loop-if-<:  # (payload primitive)
33099     0x11/imm32/alloc-id:fake:payload
33100     0x11/imm32/alloc-id:fake
33101     _string-loop-if-</imm32/name
33102     0/imm32/no-inouts
33103     0/imm32/no-inouts
33104     0/imm32/no-outputs
33105     0/imm32/no-outputs
33106     0x11/imm32/alloc-id:fake
33107     _string_0f_8c_jump_loop/imm32/subx-name
33108     0/imm32/no-rm32
33109     0/imm32/no-r32
33110     0/imm32/no-imm32
33111     0/imm32/no-imm8
33112     0/imm32/no-disp32
33113     0/imm32/no-xm32
33114     0/imm32/no-x32
33115     0x11/imm32/alloc-id:fake
33116     _Primitive-loop-if->=/imm32/next
33117 _Primitive-loop-if->=:  # (payload primitive)
33118     0x11/imm32/alloc-id:fake:payload
33119     0x11/imm32/alloc-id:fake
33120     _string-loop-if->=/imm32/name
33121     0/imm32/no-inouts
33122     0/imm32/no-inouts
33123     0/imm32/no-outputs
33124     0/imm32/no-outputs
33125     0x11/imm32/alloc-id:fake
33126     _string_0f_8d_jump_loop/imm32/subx-name
33127     0/imm32/no-rm32
33128     0/imm32/no-r32
33129     0/imm32/no-imm32
33130     0/imm32/no-imm8
33131     0/imm32/no-disp32
33132     0/imm32/no-xm32
33133     0/imm32/no-x32
33134     0x11/imm32/alloc-id:fake
33135     _Primitive-loop-if-<=/imm32/next
33136 _Primitive-loop-if-<=:  # (payload primitive)
33137     0x11/imm32/alloc-id:fake:payload
33138     0x11/imm32/alloc-id:fake
33139     _string-loop-if-<=/imm32/name
33140     0/imm32/no-inouts
33141     0/imm32/no-inouts
33142     0/imm32/no-outputs
33143     0/imm32/no-outputs
33144     0x11/imm32/alloc-id:fake
33145     _string_0f_8e_jump_loop/imm32/subx-name
33146     0/imm32/no-rm32
33147     0/imm32/no-r32
33148     0/imm32/no-imm32
33149     0/imm32/no-imm8
33150     0/imm32/no-disp32
33151     0/imm32/no-xm32
33152     0/imm32/no-x32
33153     0x11/imm32/alloc-id:fake
33154     _Primitive-loop-if->/imm32/next
33155 _Primitive-loop-if->:  # (payload primitive)
33156     0x11/imm32/alloc-id:fake:payload
33157     0x11/imm32/alloc-id:fake
33158     _string-loop-if->/imm32/name
33159     0/imm32/no-inouts
33160     0/imm32/no-inouts
33161     0/imm32/no-outputs
33162     0/imm32/no-outputs
33163     0x11/imm32/alloc-id:fake
33164     _string_0f_8f_jump_loop/imm32/subx-name
33165     0/imm32/no-rm32
33166     0/imm32/no-r32
33167     0/imm32/no-imm32
33168     0/imm32/no-imm8
33169     0/imm32/no-disp32
33170     0/imm32/no-xm32
33171     0/imm32/no-x32
33172     0x11/imm32/alloc-id:fake
33173     _Primitive-loop-if-carry/imm32/next
33174 _Primitive-loop-if-carry:  # (payload primitive)
33175     0x11/imm32/alloc-id:fake:payload
33176     0x11/imm32/alloc-id:fake
33177     _string-loop-if-carry/imm32/name
33178     0/imm32/no-inouts
33179     0/imm32/no-inouts
33180     0/imm32/no-outputs
33181     0/imm32/no-outputs
33182     0x11/imm32/alloc-id:fake
33183     _string_0f_82_jump_loop/imm32/subx-name
33184     0/imm32/no-rm32
33185     0/imm32/no-r32
33186     0/imm32/no-imm32
33187     0/imm32/no-imm8
33188     0/imm32/no-disp32
33189     0/imm32/no-xm32
33190     0/imm32/no-x32
33191     0x11/imm32/alloc-id:fake
33192     _Primitive-loop-if-not-carry/imm32/next
33193 _Primitive-loop-if-not-carry:  # (payload primitive)
33194     0x11/imm32/alloc-id:fake:payload
33195     0x11/imm32/alloc-id:fake
33196     _string-loop-if-not-carry/imm32/name
33197     0/imm32/no-inouts
33198     0/imm32/no-inouts
33199     0/imm32/no-outputs
33200     0/imm32/no-outputs
33201     0x11/imm32/alloc-id:fake
33202     _string_0f_83_jump_loop/imm32/subx-name
33203     0/imm32/no-rm32
33204     0/imm32/no-r32
33205     0/imm32/no-imm32
33206     0/imm32/no-imm8
33207     0/imm32/no-disp32
33208     0/imm32/no-xm32
33209     0/imm32/no-x32
33210     0x11/imm32/alloc-id:fake
33211     _Primitive-loop-if-overflow/imm32/next
33212 _Primitive-loop-if-overflow:  # (payload primitive)
33213     0x11/imm32/alloc-id:fake:payload
33214     0x11/imm32/alloc-id:fake
33215     _string-loop-if-overflow/imm32/name
33216     0/imm32/no-inouts
33217     0/imm32/no-inouts
33218     0/imm32/no-outputs
33219     0/imm32/no-outputs
33220     0x11/imm32/alloc-id:fake
33221     _string_0f_80_jump_loop/imm32/subx-name
33222     0/imm32/no-rm32
33223     0/imm32/no-r32
33224     0/imm32/no-imm32
33225     0/imm32/no-imm8
33226     0/imm32/no-disp32
33227     0/imm32/no-xm32
33228     0/imm32/no-x32
33229     0x11/imm32/alloc-id:fake
33230     _Primitive-loop-if-not-overflow/imm32/next
33231 _Primitive-loop-if-not-overflow:  # (payload primitive)
33232     0x11/imm32/alloc-id:fake:payload
33233     0x11/imm32/alloc-id:fake
33234     _string-loop-if-not-overflow/imm32/name
33235     0/imm32/no-inouts
33236     0/imm32/no-inouts
33237     0/imm32/no-outputs
33238     0/imm32/no-outputs
33239     0x11/imm32/alloc-id:fake
33240     _string_0f_81_jump_loop/imm32/subx-name
33241     0/imm32/no-rm32
33242     0/imm32/no-r32
33243     0/imm32/no-imm32
33244     0/imm32/no-imm8
33245     0/imm32/no-disp32
33246     0/imm32/no-xm32
33247     0/imm32/no-x32
33248     0x11/imm32/alloc-id:fake
33249     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
33250 _Primitive-loop:  # (payload primitive)
33251     0x11/imm32/alloc-id:fake:payload
33252     0x11/imm32/alloc-id:fake
33253     _string-loop/imm32/name
33254     0/imm32/no-inouts
33255     0/imm32/no-inouts
33256     0/imm32/no-outputs
33257     0/imm32/no-outputs
33258     0x11/imm32/alloc-id:fake
33259     _string_e9_jump_loop/imm32/subx-name
33260     0/imm32/no-rm32
33261     0/imm32/no-r32
33262     0/imm32/no-imm32
33263     0/imm32/no-imm8
33264     0/imm32/no-disp32
33265     0/imm32/no-xm32
33266     0/imm32/no-x32
33267     0x11/imm32/alloc-id:fake
33268     _Primitive-break-if-addr<-named/imm32/next
33269 # - branches to named blocks
33270 _Primitive-break-if-addr<-named:  # (payload primitive)
33271     0x11/imm32/alloc-id:fake:payload
33272     0x11/imm32/alloc-id:fake
33273     _string-break-if-addr</imm32/name
33274     0x11/imm32/alloc-id:fake
33275     Single-lit-var/imm32/inouts
33276     0/imm32/no-outputs
33277     0/imm32/no-outputs
33278     0x11/imm32/alloc-id:fake
33279     _string_0f_82_jump_label/imm32/subx-name
33280     0/imm32/no-rm32
33281     0/imm32/no-r32
33282     0/imm32/no-imm32
33283     0/imm32/no-imm8
33284     1/imm32/disp32-is-first-inout
33285     0/imm32/no-xm32
33286     0/imm32/no-x32
33287     0x11/imm32/alloc-id:fake
33288     _Primitive-break-if-addr>=-named/imm32/next
33289 _Primitive-break-if-addr>=-named:  # (payload primitive)
33290     0x11/imm32/alloc-id:fake:payload
33291     0x11/imm32/alloc-id:fake
33292     _string-break-if-addr>=/imm32/name
33293     0x11/imm32/alloc-id:fake
33294     Single-lit-var/imm32/inouts
33295     0/imm32/no-outputs
33296     0/imm32/no-outputs
33297     0x11/imm32/alloc-id:fake
33298     _string_0f_83_jump_label/imm32/subx-name
33299     0/imm32/no-rm32
33300     0/imm32/no-r32
33301     0/imm32/no-imm32
33302     0/imm32/no-imm8
33303     1/imm32/disp32-is-first-inout
33304     0/imm32/no-xm32
33305     0/imm32/no-x32
33306     0x11/imm32/alloc-id:fake
33307     _Primitive-break-if-=-named/imm32/next
33308 _Primitive-break-if-=-named:  # (payload primitive)
33309     0x11/imm32/alloc-id:fake:payload
33310     0x11/imm32/alloc-id:fake
33311     _string-break-if-=/imm32/name
33312     0x11/imm32/alloc-id:fake
33313     Single-lit-var/imm32/inouts
33314     0/imm32/no-outputs
33315     0/imm32/no-outputs
33316     0x11/imm32/alloc-id:fake
33317     _string_0f_84_jump_label/imm32/subx-name
33318     0/imm32/no-rm32
33319     0/imm32/no-r32
33320     0/imm32/no-imm32
33321     0/imm32/no-imm8
33322     1/imm32/disp32-is-first-inout
33323     0/imm32/no-xm32
33324     0/imm32/no-x32
33325     0x11/imm32/alloc-id:fake
33326     _Primitive-break-if-!=-named/imm32/next
33327 _Primitive-break-if-!=-named:  # (payload primitive)
33328     0x11/imm32/alloc-id:fake:payload
33329     0x11/imm32/alloc-id:fake
33330     _string-break-if-!=/imm32/name
33331     0x11/imm32/alloc-id:fake
33332     Single-lit-var/imm32/inouts
33333     0/imm32/no-outputs
33334     0/imm32/no-outputs
33335     0x11/imm32/alloc-id:fake
33336     _string_0f_85_jump_label/imm32/subx-name
33337     0/imm32/no-rm32
33338     0/imm32/no-r32
33339     0/imm32/no-imm32
33340     0/imm32/no-imm8
33341     1/imm32/disp32-is-first-inout
33342     0/imm32/no-xm32
33343     0/imm32/no-x32
33344     0x11/imm32/alloc-id:fake
33345     _Primitive-break-if-addr<=-named/imm32/next
33346 _Primitive-break-if-addr<=-named:  # (payload primitive)
33347     0x11/imm32/alloc-id:fake:payload
33348     0x11/imm32/alloc-id:fake
33349     _string-break-if-addr<=/imm32/name
33350     0x11/imm32/alloc-id:fake
33351     Single-lit-var/imm32/inouts
33352     0/imm32/no-outputs
33353     0/imm32/no-outputs
33354     0x11/imm32/alloc-id:fake
33355     _string_0f_86_jump_label/imm32/subx-name
33356     0/imm32/no-rm32
33357     0/imm32/no-r32
33358     0/imm32/no-imm32
33359     0/imm32/no-imm8
33360     1/imm32/disp32-is-first-inout
33361     0/imm32/no-xm32
33362     0/imm32/no-x32
33363     0x11/imm32/alloc-id:fake
33364     _Primitive-break-if-addr>-named/imm32/next
33365 _Primitive-break-if-addr>-named:  # (payload primitive)
33366     0x11/imm32/alloc-id:fake:payload
33367     0x11/imm32/alloc-id:fake
33368     _string-break-if-addr>/imm32/name
33369     0x11/imm32/alloc-id:fake
33370     Single-lit-var/imm32/inouts
33371     0/imm32/no-outputs
33372     0/imm32/no-outputs
33373     0x11/imm32/alloc-id:fake
33374     _string_0f_87_jump_label/imm32/subx-name
33375     0/imm32/no-rm32
33376     0/imm32/no-r32
33377     0/imm32/no-imm32
33378     0/imm32/no-imm8
33379     1/imm32/disp32-is-first-inout
33380     0/imm32/no-xm32
33381     0/imm32/no-x32
33382     0x11/imm32/alloc-id:fake
33383     _Primitive-break-if-<-named/imm32/next
33384 _Primitive-break-if-<-named:  # (payload primitive)
33385     0x11/imm32/alloc-id:fake:payload
33386     0x11/imm32/alloc-id:fake
33387     _string-break-if-</imm32/name
33388     0x11/imm32/alloc-id:fake
33389     Single-lit-var/imm32/inouts
33390     0/imm32/no-outputs
33391     0/imm32/no-outputs
33392     0x11/imm32/alloc-id:fake
33393     _string_0f_8c_jump_label/imm32/subx-name
33394     0/imm32/no-rm32
33395     0/imm32/no-r32
33396     0/imm32/no-imm32
33397     0/imm32/no-imm8
33398     1/imm32/disp32-is-first-inout
33399     0/imm32/no-xm32
33400     0/imm32/no-x32
33401     0x11/imm32/alloc-id:fake
33402     _Primitive-break-if->=-named/imm32/next
33403 _Primitive-break-if->=-named:  # (payload primitive)
33404     0x11/imm32/alloc-id:fake:payload
33405     0x11/imm32/alloc-id:fake
33406     _string-break-if->=/imm32/name
33407     0x11/imm32/alloc-id:fake
33408     Single-lit-var/imm32/inouts
33409     0/imm32/no-outputs
33410     0/imm32/no-outputs
33411     0x11/imm32/alloc-id:fake
33412     _string_0f_8d_jump_label/imm32/subx-name
33413     0/imm32/no-rm32
33414     0/imm32/no-r32
33415     0/imm32/no-imm32
33416     0/imm32/no-imm8
33417     1/imm32/disp32-is-first-inout
33418     0/imm32/no-xm32
33419     0/imm32/no-x32
33420     0x11/imm32/alloc-id:fake
33421     _Primitive-break-if-<=-named/imm32/next
33422 _Primitive-break-if-<=-named:  # (payload primitive)
33423     0x11/imm32/alloc-id:fake:payload
33424     0x11/imm32/alloc-id:fake
33425     _string-break-if-<=/imm32/name
33426     0x11/imm32/alloc-id:fake
33427     Single-lit-var/imm32/inouts
33428     0/imm32/no-outputs
33429     0/imm32/no-outputs
33430     0x11/imm32/alloc-id:fake
33431     _string_0f_8e_jump_label/imm32/subx-name
33432     0/imm32/no-rm32
33433     0/imm32/no-r32
33434     0/imm32/no-imm32
33435     0/imm32/no-imm8
33436     1/imm32/disp32-is-first-inout
33437     0/imm32/no-xm32
33438     0/imm32/no-x32
33439     0x11/imm32/alloc-id:fake
33440     _Primitive-break-if->-named/imm32/next
33441 _Primitive-break-if->-named:  # (payload primitive)
33442     0x11/imm32/alloc-id:fake:payload
33443     0x11/imm32/alloc-id:fake
33444     _string-break-if->/imm32/name
33445     0x11/imm32/alloc-id:fake
33446     Single-lit-var/imm32/inouts
33447     0/imm32/no-outputs
33448     0/imm32/no-outputs
33449     0x11/imm32/alloc-id:fake
33450     _string_0f_8f_jump_label/imm32/subx-name
33451     0/imm32/no-rm32
33452     0/imm32/no-r32
33453     0/imm32/no-imm32
33454     0/imm32/no-imm8
33455     1/imm32/disp32-is-first-inout
33456     0/imm32/no-xm32
33457     0/imm32/no-x32
33458     0x11/imm32/alloc-id:fake
33459     _Primitive-break-named/imm32/next
33460 _Primitive-break-named:  # (payload primitive)
33461     0x11/imm32/alloc-id:fake:payload
33462     0x11/imm32/alloc-id:fake
33463     _string-break/imm32/name
33464     0x11/imm32/alloc-id:fake
33465     Single-lit-var/imm32/inouts
33466     0/imm32/no-outputs
33467     0/imm32/no-outputs
33468     0x11/imm32/alloc-id:fake
33469     _string_e9_jump_label/imm32/subx-name
33470     0/imm32/no-rm32
33471     0/imm32/no-r32
33472     0/imm32/no-imm32
33473     0/imm32/no-imm8
33474     1/imm32/disp32-is-first-inout
33475     0/imm32/no-xm32
33476     0/imm32/no-x32
33477     0x11/imm32/alloc-id:fake
33478     _Primitive-loop-if-addr<-named/imm32/next
33479 _Primitive-loop-if-addr<-named:  # (payload primitive)
33480     0x11/imm32/alloc-id:fake:payload
33481     0x11/imm32/alloc-id:fake
33482     _string-loop-if-addr</imm32/name
33483     0x11/imm32/alloc-id:fake
33484     Single-lit-var/imm32/inouts
33485     0/imm32/no-outputs
33486     0/imm32/no-outputs
33487     0x11/imm32/alloc-id:fake
33488     _string_0f_82_jump_label/imm32/subx-name
33489     0/imm32/no-rm32
33490     0/imm32/no-r32
33491     0/imm32/no-imm32
33492     0/imm32/no-imm8
33493     1/imm32/disp32-is-first-inout
33494     0/imm32/no-xm32
33495     0/imm32/no-x32
33496     0x11/imm32/alloc-id:fake
33497     _Primitive-loop-if-addr>=-named/imm32/next
33498 _Primitive-loop-if-addr>=-named:  # (payload primitive)
33499     0x11/imm32/alloc-id:fake:payload
33500     0x11/imm32/alloc-id:fake
33501     _string-loop-if-addr>=/imm32/name
33502     0x11/imm32/alloc-id:fake
33503     Single-lit-var/imm32/inouts
33504     0/imm32/no-outputs
33505     0/imm32/no-outputs
33506     0x11/imm32/alloc-id:fake
33507     _string_0f_83_jump_label/imm32/subx-name
33508     0/imm32/no-rm32
33509     0/imm32/no-r32
33510     0/imm32/no-imm32
33511     0/imm32/no-imm8
33512     1/imm32/disp32-is-first-inout
33513     0/imm32/no-xm32
33514     0/imm32/no-x32
33515     0x11/imm32/alloc-id:fake
33516     _Primitive-loop-if-=-named/imm32/next
33517 _Primitive-loop-if-=-named:  # (payload primitive)
33518     0x11/imm32/alloc-id:fake:payload
33519     0x11/imm32/alloc-id:fake
33520     _string-loop-if-=/imm32/name
33521     0x11/imm32/alloc-id:fake
33522     Single-lit-var/imm32/inouts
33523     0/imm32/no-outputs
33524     0/imm32/no-outputs
33525     0x11/imm32/alloc-id:fake
33526     _string_0f_84_jump_label/imm32/subx-name
33527     0/imm32/no-rm32
33528     0/imm32/no-r32
33529     0/imm32/no-imm32
33530     0/imm32/no-imm8
33531     1/imm32/disp32-is-first-inout
33532     0/imm32/no-xm32
33533     0/imm32/no-x32
33534     0x11/imm32/alloc-id:fake
33535     _Primitive-loop-if-!=-named/imm32/next
33536 _Primitive-loop-if-!=-named:  # (payload primitive)
33537     0x11/imm32/alloc-id:fake:payload
33538     0x11/imm32/alloc-id:fake
33539     _string-loop-if-!=/imm32/name
33540     0x11/imm32/alloc-id:fake
33541     Single-lit-var/imm32/inouts
33542     0/imm32/no-outputs
33543     0/imm32/no-outputs
33544     0x11/imm32/alloc-id:fake
33545     _string_0f_85_jump_label/imm32/subx-name
33546     0/imm32/no-rm32
33547     0/imm32/no-r32
33548     0/imm32/no-imm32
33549     0/imm32/no-imm8
33550     1/imm32/disp32-is-first-inout
33551     0/imm32/no-xm32
33552     0/imm32/no-x32
33553     0x11/imm32/alloc-id:fake
33554     _Primitive-loop-if-addr<=-named/imm32/next
33555 _Primitive-loop-if-addr<=-named:  # (payload primitive)
33556     0x11/imm32/alloc-id:fake:payload
33557     0x11/imm32/alloc-id:fake
33558     _string-loop-if-addr<=/imm32/name
33559     0x11/imm32/alloc-id:fake
33560     Single-lit-var/imm32/inouts
33561     0/imm32/no-outputs
33562     0/imm32/no-outputs
33563     0x11/imm32/alloc-id:fake
33564     _string_0f_86_jump_label/imm32/subx-name
33565     0/imm32/no-rm32
33566     0/imm32/no-r32
33567     0/imm32/no-imm32
33568     0/imm32/no-imm8
33569     1/imm32/disp32-is-first-inout
33570     0/imm32/no-xm32
33571     0/imm32/no-x32
33572     0x11/imm32/alloc-id:fake
33573     _Primitive-loop-if-addr>-named/imm32/next
33574 _Primitive-loop-if-addr>-named:  # (payload primitive)
33575     0x11/imm32/alloc-id:fake:payload
33576     0x11/imm32/alloc-id:fake
33577     _string-loop-if-addr>/imm32/name
33578     0x11/imm32/alloc-id:fake
33579     Single-lit-var/imm32/inouts
33580     0/imm32/no-outputs
33581     0/imm32/no-outputs
33582     0x11/imm32/alloc-id:fake
33583     _string_0f_87_jump_label/imm32/subx-name
33584     0/imm32/no-rm32
33585     0/imm32/no-r32
33586     0/imm32/no-imm32
33587     0/imm32/no-imm8
33588     1/imm32/disp32-is-first-inout
33589     0/imm32/no-xm32
33590     0/imm32/no-x32
33591     0x11/imm32/alloc-id:fake
33592     _Primitive-loop-if-<-named/imm32/next
33593 _Primitive-loop-if-<-named:  # (payload primitive)
33594     0x11/imm32/alloc-id:fake:payload
33595     0x11/imm32/alloc-id:fake
33596     _string-loop-if-</imm32/name
33597     0x11/imm32/alloc-id:fake
33598     Single-lit-var/imm32/inouts
33599     0/imm32/no-outputs
33600     0/imm32/no-outputs
33601     0x11/imm32/alloc-id:fake
33602     _string_0f_8c_jump_label/imm32/subx-name
33603     0/imm32/no-rm32
33604     0/imm32/no-r32
33605     0/imm32/no-imm32
33606     0/imm32/no-imm8
33607     1/imm32/disp32-is-first-inout
33608     0/imm32/no-xm32
33609     0/imm32/no-x32
33610     0x11/imm32/alloc-id:fake
33611     _Primitive-loop-if->=-named/imm32/next
33612 _Primitive-loop-if->=-named:  # (payload primitive)
33613     0x11/imm32/alloc-id:fake:payload
33614     0x11/imm32/alloc-id:fake
33615     _string-loop-if->=/imm32/name
33616     0x11/imm32/alloc-id:fake
33617     Single-lit-var/imm32/inouts
33618     0/imm32/no-outputs
33619     0/imm32/no-outputs
33620     0x11/imm32/alloc-id:fake
33621     _string_0f_8d_jump_label/imm32/subx-name
33622     0/imm32/no-rm32
33623     0/imm32/no-r32
33624     0/imm32/no-imm32
33625     0/imm32/no-imm8
33626     1/imm32/disp32-is-first-inout
33627     0/imm32/no-xm32
33628     0/imm32/no-x32
33629     0x11/imm32/alloc-id:fake
33630     _Primitive-loop-if-<=-named/imm32/next
33631 _Primitive-loop-if-<=-named:  # (payload primitive)
33632     0x11/imm32/alloc-id:fake:payload
33633     0x11/imm32/alloc-id:fake
33634     _string-loop-if-<=/imm32/name
33635     0x11/imm32/alloc-id:fake
33636     Single-lit-var/imm32/inouts
33637     0/imm32/no-outputs
33638     0/imm32/no-outputs
33639     0x11/imm32/alloc-id:fake
33640     _string_0f_8e_jump_label/imm32/subx-name
33641     0/imm32/no-rm32
33642     0/imm32/no-r32
33643     0/imm32/no-imm32
33644     0/imm32/no-imm8
33645     1/imm32/disp32-is-first-inout
33646     0/imm32/no-xm32
33647     0/imm32/no-x32
33648     0x11/imm32/alloc-id:fake
33649     _Primitive-loop-if->-named/imm32/next
33650 _Primitive-loop-if->-named:  # (payload primitive)
33651     0x11/imm32/alloc-id:fake:payload
33652     0x11/imm32/alloc-id:fake
33653     _string-loop-if->/imm32/name
33654     0x11/imm32/alloc-id:fake
33655     Single-lit-var/imm32/inouts
33656     0/imm32/no-outputs
33657     0/imm32/no-outputs
33658     0x11/imm32/alloc-id:fake
33659     _string_0f_8f_jump_label/imm32/subx-name
33660     0/imm32/no-rm32
33661     0/imm32/no-r32
33662     0/imm32/no-imm32
33663     0/imm32/no-imm8
33664     1/imm32/disp32-is-first-inout
33665     0/imm32/no-xm32
33666     0/imm32/no-x32
33667     0x11/imm32/alloc-id:fake
33668     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
33669 _Primitive-loop-named:  # (payload primitive)
33670     0x11/imm32/alloc-id:fake:payload
33671     0x11/imm32/alloc-id:fake
33672     _string-loop/imm32/name
33673     0x11/imm32/alloc-id:fake
33674     Single-lit-var/imm32/inouts
33675     0/imm32/no-outputs
33676     0/imm32/no-outputs
33677     0x11/imm32/alloc-id:fake
33678     _string_e9_jump_label/imm32/subx-name
33679     0/imm32/no-rm32
33680     0/imm32/no-r32
33681     0/imm32/no-imm32
33682     0/imm32/no-imm8
33683     1/imm32/disp32-is-first-inout
33684     0/imm32/no-xm32
33685     0/imm32/no-x32
33686     0x11/imm32/alloc-id:fake
33687     _Primitive-break-if-float</imm32/next
33688 # - branches based on floating-point comparisons
33689 _Primitive-break-if-float<:  # (payload primitive)
33690     0x11/imm32/alloc-id:fake:payload
33691     0x11/imm32/alloc-id:fake
33692     _string-break-if-float</imm32/name
33693     0/imm32/no-inouts
33694     0/imm32/no-inouts
33695     0/imm32/no-outputs
33696     0/imm32/no-outputs
33697     0x11/imm32/alloc-id:fake
33698     _string_0f_82_jump_break/imm32/subx-name
33699     0/imm32/no-rm32
33700     0/imm32/no-r32
33701     0/imm32/no-imm32
33702     0/imm32/no-imm8
33703     0/imm32/no-disp32
33704     0/imm32/no-xm32
33705     0/imm32/no-x32
33706     0x11/imm32/alloc-id:fake
33707     _Primitive-break-if-float>=/imm32/next
33708 _Primitive-break-if-float>=:  # (payload primitive)
33709     0x11/imm32/alloc-id:fake:payload
33710     0x11/imm32/alloc-id:fake
33711     _string-break-if-float>=/imm32/name
33712     0/imm32/no-inouts
33713     0/imm32/no-inouts
33714     0/imm32/no-outputs
33715     0/imm32/no-outputs
33716     0x11/imm32/alloc-id:fake
33717     _string_0f_83_jump_break/imm32/subx-name
33718     0/imm32/no-rm32
33719     0/imm32/no-r32
33720     0/imm32/no-imm32
33721     0/imm32/no-imm8
33722     0/imm32/no-disp32
33723     0/imm32/no-xm32
33724     0/imm32/no-x32
33725     0x11/imm32/alloc-id:fake
33726     _Primitive-break-if-float<=/imm32/next
33727 _Primitive-break-if-float<=:  # (payload primitive)
33728     0x11/imm32/alloc-id:fake:payload
33729     0x11/imm32/alloc-id:fake
33730     _string-break-if-float<=/imm32/name
33731     0/imm32/no-inouts
33732     0/imm32/no-inouts
33733     0/imm32/no-outputs
33734     0/imm32/no-outputs
33735     0x11/imm32/alloc-id:fake
33736     _string_0f_86_jump_break/imm32/subx-name
33737     0/imm32/no-rm32
33738     0/imm32/no-r32
33739     0/imm32/no-imm32
33740     0/imm32/no-imm8
33741     0/imm32/no-disp32
33742     0/imm32/no-xm32
33743     0/imm32/no-x32
33744     0x11/imm32/alloc-id:fake
33745     _Primitive-break-if-float>/imm32/next
33746 _Primitive-break-if-float>:  # (payload primitive)
33747     0x11/imm32/alloc-id:fake:payload
33748     0x11/imm32/alloc-id:fake
33749     _string-break-if-float>/imm32/name
33750     0/imm32/no-inouts
33751     0/imm32/no-inouts
33752     0/imm32/no-outputs
33753     0/imm32/no-outputs
33754     0x11/imm32/alloc-id:fake
33755     _string_0f_87_jump_break/imm32/subx-name
33756     0/imm32/no-rm32
33757     0/imm32/no-r32
33758     0/imm32/no-imm32
33759     0/imm32/no-imm8
33760     0/imm32/no-disp32
33761     0/imm32/no-xm32
33762     0/imm32/no-x32
33763     0x11/imm32/alloc-id:fake
33764     _Primitive-loop-if-float</imm32/next
33765 _Primitive-loop-if-float<:  # (payload primitive)
33766     0x11/imm32/alloc-id:fake:payload
33767     0x11/imm32/alloc-id:fake
33768     _string-loop-if-float</imm32/name
33769     0/imm32/no-inouts
33770     0/imm32/no-inouts
33771     0/imm32/no-outputs
33772     0/imm32/no-outputs
33773     0x11/imm32/alloc-id:fake
33774     _string_0f_82_jump_loop/imm32/subx-name
33775     0/imm32/no-rm32
33776     0/imm32/no-r32
33777     0/imm32/no-imm32
33778     0/imm32/no-imm8
33779     0/imm32/no-disp32
33780     0/imm32/no-xm32
33781     0/imm32/no-x32
33782     0x11/imm32/alloc-id:fake
33783     _Primitive-loop-if-float>=/imm32/next
33784 _Primitive-loop-if-float>=:  # (payload primitive)
33785     0x11/imm32/alloc-id:fake:payload
33786     0x11/imm32/alloc-id:fake
33787     _string-loop-if-float>=/imm32/name
33788     0/imm32/no-inouts
33789     0/imm32/no-inouts
33790     0/imm32/no-outputs
33791     0/imm32/no-outputs
33792     0x11/imm32/alloc-id:fake
33793     _string_0f_83_jump_loop/imm32/subx-name
33794     0/imm32/no-rm32
33795     0/imm32/no-r32
33796     0/imm32/no-imm32
33797     0/imm32/no-imm8
33798     0/imm32/no-disp32
33799     0/imm32/no-xm32
33800     0/imm32/no-x32
33801     0x11/imm32/alloc-id:fake
33802     _Primitive-loop-if-float<=/imm32/next
33803 _Primitive-loop-if-float<=:  # (payload primitive)
33804     0x11/imm32/alloc-id:fake:payload
33805     0x11/imm32/alloc-id:fake
33806     _string-loop-if-float<=/imm32/name
33807     0/imm32/no-inouts
33808     0/imm32/no-inouts
33809     0/imm32/no-outputs
33810     0/imm32/no-outputs
33811     0x11/imm32/alloc-id:fake
33812     _string_0f_86_jump_loop/imm32/subx-name
33813     0/imm32/no-rm32
33814     0/imm32/no-r32
33815     0/imm32/no-imm32
33816     0/imm32/no-imm8
33817     0/imm32/no-disp32
33818     0/imm32/no-xm32
33819     0/imm32/no-x32
33820     0x11/imm32/alloc-id:fake
33821     _Primitive-loop-if-float>/imm32/next
33822 _Primitive-loop-if-float>:  # (payload primitive)
33823     0x11/imm32/alloc-id:fake:payload
33824     0x11/imm32/alloc-id:fake
33825     _string-loop-if-float>/imm32/name
33826     0/imm32/no-inouts
33827     0/imm32/no-inouts
33828     0/imm32/no-outputs
33829     0/imm32/no-outputs
33830     0x11/imm32/alloc-id:fake
33831     _string_0f_87_jump_loop/imm32/subx-name
33832     0/imm32/no-rm32
33833     0/imm32/no-r32
33834     0/imm32/no-imm32
33835     0/imm32/no-imm8
33836     0/imm32/no-disp32
33837     0/imm32/no-xm32
33838     0/imm32/no-x32
33839     0x11/imm32/alloc-id:fake
33840     _Primitive-break-if-float<-named/imm32/next
33841 _Primitive-break-if-float<-named:  # (payload primitive)
33842     0x11/imm32/alloc-id:fake:payload
33843     0x11/imm32/alloc-id:fake
33844     _string-break-if-float</imm32/name
33845     0x11/imm32/alloc-id:fake
33846     Single-lit-var/imm32/inouts
33847     0/imm32/no-outputs
33848     0/imm32/no-outputs
33849     0x11/imm32/alloc-id:fake
33850     _string_0f_82_jump_label/imm32/subx-name
33851     0/imm32/no-rm32
33852     0/imm32/no-r32
33853     0/imm32/no-imm32
33854     0/imm32/no-imm8
33855     1/imm32/disp32-is-first-inout
33856     0/imm32/no-xm32
33857     0/imm32/no-x32
33858     0x11/imm32/alloc-id:fake
33859     _Primitive-break-if-float>=-named/imm32/next
33860 _Primitive-break-if-float>=-named:  # (payload primitive)
33861     0x11/imm32/alloc-id:fake:payload
33862     0x11/imm32/alloc-id:fake
33863     _string-break-if-float>=/imm32/name
33864     0x11/imm32/alloc-id:fake
33865     Single-lit-var/imm32/inouts
33866     0/imm32/no-outputs
33867     0/imm32/no-outputs
33868     0x11/imm32/alloc-id:fake
33869     _string_0f_83_jump_label/imm32/subx-name
33870     0/imm32/no-rm32
33871     0/imm32/no-r32
33872     0/imm32/no-imm32
33873     0/imm32/no-imm8
33874     1/imm32/disp32-is-first-inout
33875     0/imm32/no-xm32
33876     0/imm32/no-x32
33877     0x11/imm32/alloc-id:fake
33878     _Primitive-break-if-float<=-named/imm32/next
33879 _Primitive-break-if-float<=-named:  # (payload primitive)
33880     0x11/imm32/alloc-id:fake:payload
33881     0x11/imm32/alloc-id:fake
33882     _string-break-if-float<=/imm32/name
33883     0x11/imm32/alloc-id:fake
33884     Single-lit-var/imm32/inouts
33885     0/imm32/no-outputs
33886     0/imm32/no-outputs
33887     0x11/imm32/alloc-id:fake
33888     _string_0f_86_jump_label/imm32/subx-name
33889     0/imm32/no-rm32
33890     0/imm32/no-r32
33891     0/imm32/no-imm32
33892     0/imm32/no-imm8
33893     1/imm32/disp32-is-first-inout
33894     0/imm32/no-xm32
33895     0/imm32/no-x32
33896     0x11/imm32/alloc-id:fake
33897     _Primitive-break-if-float>-named/imm32/next
33898 _Primitive-break-if-float>-named:  # (payload primitive)
33899     0x11/imm32/alloc-id:fake:payload
33900     0x11/imm32/alloc-id:fake
33901     _string-break-if-float>/imm32/name
33902     0x11/imm32/alloc-id:fake
33903     Single-lit-var/imm32/inouts
33904     0/imm32/no-outputs
33905     0/imm32/no-outputs
33906     0x11/imm32/alloc-id:fake
33907     _string_0f_87_jump_label/imm32/subx-name
33908     0/imm32/no-rm32
33909     0/imm32/no-r32
33910     0/imm32/no-imm32
33911     0/imm32/no-imm8
33912     1/imm32/disp32-is-first-inout
33913     0/imm32/no-xm32
33914     0/imm32/no-x32
33915     0x11/imm32/alloc-id:fake
33916     _Primitive-loop-if-float<-named/imm32/next
33917 _Primitive-loop-if-float<-named:  # (payload primitive)
33918     0x11/imm32/alloc-id:fake:payload
33919     0x11/imm32/alloc-id:fake
33920     _string-loop-if-float</imm32/name
33921     0x11/imm32/alloc-id:fake
33922     Single-lit-var/imm32/inouts
33923     0/imm32/no-outputs
33924     0/imm32/no-outputs
33925     0x11/imm32/alloc-id:fake
33926     _string_0f_82_jump_label/imm32/subx-name
33927     0/imm32/no-rm32
33928     0/imm32/no-r32
33929     0/imm32/no-imm32
33930     0/imm32/no-imm8
33931     1/imm32/disp32-is-first-inout
33932     0/imm32/no-xm32
33933     0/imm32/no-x32
33934     0x11/imm32/alloc-id:fake
33935     _Primitive-loop-if-float>=-named/imm32/next
33936 _Primitive-loop-if-float>=-named:  # (payload primitive)
33937     0x11/imm32/alloc-id:fake:payload
33938     0x11/imm32/alloc-id:fake
33939     _string-loop-if-float>=/imm32/name
33940     0x11/imm32/alloc-id:fake
33941     Single-lit-var/imm32/inouts
33942     0/imm32/no-outputs
33943     0/imm32/no-outputs
33944     0x11/imm32/alloc-id:fake
33945     _string_0f_83_jump_label/imm32/subx-name
33946     0/imm32/no-rm32
33947     0/imm32/no-r32
33948     0/imm32/no-imm32
33949     0/imm32/no-imm8
33950     1/imm32/disp32-is-first-inout
33951     0/imm32/no-xm32
33952     0/imm32/no-x32
33953     0x11/imm32/alloc-id:fake
33954     _Primitive-loop-if-float<=-named/imm32/next
33955 _Primitive-loop-if-float<=-named:  # (payload primitive)
33956     0x11/imm32/alloc-id:fake:payload
33957     0x11/imm32/alloc-id:fake
33958     _string-loop-if-float<=/imm32/name
33959     0x11/imm32/alloc-id:fake
33960     Single-lit-var/imm32/inouts
33961     0/imm32/no-outputs
33962     0/imm32/no-outputs
33963     0x11/imm32/alloc-id:fake
33964     _string_0f_86_jump_label/imm32/subx-name
33965     0/imm32/no-rm32
33966     0/imm32/no-r32
33967     0/imm32/no-imm32
33968     0/imm32/no-imm8
33969     1/imm32/disp32-is-first-inout
33970     0/imm32/no-xm32
33971     0/imm32/no-x32
33972     0x11/imm32/alloc-id:fake
33973     _Primitive-loop-if-float>-named/imm32/next
33974 _Primitive-loop-if-float>-named:  # (payload primitive)
33975     0x11/imm32/alloc-id:fake:payload
33976     0x11/imm32/alloc-id:fake
33977     _string-loop-if-float>/imm32/name
33978     0x11/imm32/alloc-id:fake
33979     Single-lit-var/imm32/inouts
33980     0/imm32/no-outputs
33981     0/imm32/no-outputs
33982     0x11/imm32/alloc-id:fake
33983     _string_0f_87_jump_label/imm32/subx-name
33984     0/imm32/no-rm32
33985     0/imm32/no-r32
33986     0/imm32/no-imm32
33987     0/imm32/no-imm8
33988     1/imm32/disp32-is-first-inout
33989     0/imm32/no-xm32
33990     0/imm32/no-x32
33991     0/imm32/next
33992     0/imm32/next
33993 
33994 # string literals for Mu instructions
33995 _string-add:  # (payload array byte)
33996     0x11/imm32/alloc-id:fake:payload
33997     # "add"
33998     0x3/imm32/size
33999     0x61/a 0x64/d 0x64/d
34000 _string-address:  # (payload array byte)
34001     0x11/imm32/alloc-id:fake:payload
34002     # "address"
34003     0x7/imm32/size
34004     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
34005 _string-add-to:  # (payload array byte)
34006     0x11/imm32/alloc-id:fake:payload
34007     # "add-to"
34008     0x6/imm32/size
34009     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
34010 _string-and:  # (payload array byte)
34011     0x11/imm32/alloc-id:fake:payload
34012     # "and"
34013     0x3/imm32/size
34014     0x61/a 0x6e/n 0x64/d
34015 _string-and-with:  # (payload array byte)
34016     0x11/imm32/alloc-id:fake:payload
34017     # "and-with"
34018     0x8/imm32/size
34019     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34020 _string-break:  # (payload array byte)
34021     0x11/imm32/alloc-id:fake:payload
34022     # "break"
34023     0x5/imm32/size
34024     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
34025 _string-break-if-<:  # (payload array byte)
34026     0x11/imm32/alloc-id:fake:payload
34027     # "break-if-<"
34028     0xa/imm32/size
34029     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
34030 _string-break-if-<=:  # (payload array byte)
34031     0x11/imm32/alloc-id:fake:payload
34032     # "break-if-<="
34033     0xb/imm32/size
34034     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
34035 _string-break-if-=:  # (payload array byte)
34036     0x11/imm32/alloc-id:fake:payload
34037     # "break-if-="
34038     0xa/imm32/size
34039     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
34040 _string-break-if->:  # (payload array byte)
34041     0x11/imm32/alloc-id:fake:payload
34042     # "break-if->"
34043     0xa/imm32/size
34044     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
34045 _string-break-if->=:  # (payload array byte)
34046     0x11/imm32/alloc-id:fake:payload
34047     # "break-if->="
34048     0xb/imm32/size
34049     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
34050 _string-break-if-!=:  # (payload array byte)
34051     0x11/imm32/alloc-id:fake:payload
34052     # "break-if-!="
34053     0xb/imm32/size
34054     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
34055 _string-break-if-addr<:  # (payload array byte)
34056     0x11/imm32/alloc-id:fake:payload
34057     # "break-if-addr<"
34058     0xe/imm32/size
34059     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
34060 _string-break-if-addr<=:  # (payload array byte)
34061     0x11/imm32/alloc-id:fake:payload
34062     # "break-if-addr<="
34063     0xf/imm32/size
34064     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
34065 _string-break-if-addr>:  # (payload array byte)
34066     0x11/imm32/alloc-id:fake:payload
34067     # "break-if-addr>"
34068     0xe/imm32/size
34069     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
34070 _string-break-if-addr>=:  # (payload array byte)
34071     0x11/imm32/alloc-id:fake:payload
34072     # "break-if-addr>="
34073     0xf/imm32/size
34074     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
34075 _string-break-if-float<:  # (payload array byte)
34076     0x11/imm32/alloc-id:fake:payload
34077     # "break-if-float<"
34078     0xf/imm32/size
34079     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
34080 _string-break-if-float<=:  # (payload array byte)
34081     0x11/imm32/alloc-id:fake:payload
34082     # "break-if-float<="
34083     0x10/imm32/size
34084     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
34085 _string-break-if-float>:  # (payload array byte)
34086     0x11/imm32/alloc-id:fake:payload
34087     # "break-if-float>"
34088     0xf/imm32/size
34089     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
34090 _string-break-if-float>=:  # (payload array byte)
34091     0x11/imm32/alloc-id:fake:payload
34092     # "break-if-float>="
34093     0x10/imm32/size
34094     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
34095 _string-break-if-carry:  # (payload array byte)
34096     0x11/imm32/alloc-id:fake:payload
34097     # "break-if-carry"
34098     0xe/imm32/size
34099     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34100 _string-break-if-not-carry:  # (payload array byte)
34101     0x11/imm32/alloc-id:fake:payload
34102     # "break-if-not-carry"
34103     0x12/imm32/size
34104     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34105 _string-break-if-overflow:  # (payload array byte)
34106     0x11/imm32/alloc-id:fake:payload
34107     # "break-if-overflow"
34108     0x11/imm32/size
34109     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34110 _string-break-if-not-overflow:  # (payload array byte)
34111     0x11/imm32/alloc-id:fake:payload
34112     # "break-if-not-overflow"
34113     0x15/imm32/size
34114     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34115 _string-compare:  # (payload array byte)
34116     0x11/imm32/alloc-id:fake:payload
34117     # "compare"
34118     0x7/imm32/size
34119     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
34120 _string-copy:  # (payload array byte)
34121     0x11/imm32/alloc-id:fake:payload
34122     # "copy"
34123     0x4/imm32/size
34124     0x63/c 0x6f/o 0x70/p 0x79/y
34125 _string-copy-to:  # (payload array byte)
34126     0x11/imm32/alloc-id:fake:payload
34127     # "copy-to"
34128     0x7/imm32/size
34129     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
34130 _string-copy-byte:
34131     0x11/imm32/alloc-id:fake:payload
34132     # "copy-byte"
34133     0x9/imm32/size
34134     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e
34135 _string-copy-byte-to:
34136     0x11/imm32/alloc-id:fake:payload
34137     # "copy-byte-to"
34138     0xc/imm32/size
34139     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o
34140 _string-decrement:  # (payload array byte)
34141     0x11/imm32/alloc-id:fake:payload
34142     # "decrement"
34143     0x9/imm32/size
34144     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
34145 _string-increment:  # (payload array byte)
34146     0x11/imm32/alloc-id:fake:payload
34147     # "increment"
34148     0x9/imm32/size
34149     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
34150 _string-loop:  # (payload array byte)
34151     0x11/imm32/alloc-id:fake:payload
34152     # "loop"
34153     0x4/imm32/size
34154     0x6c/l 0x6f/o 0x6f/o 0x70/p
34155 _string-loop-if-<:  # (payload array byte)
34156     0x11/imm32/alloc-id:fake:payload
34157     # "loop-if-<"
34158     0x9/imm32/size
34159     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
34160 _string-loop-if-<=:  # (payload array byte)
34161     0x11/imm32/alloc-id:fake:payload
34162     # "loop-if-<="
34163     0xa/imm32/size
34164     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
34165 _string-loop-if-=:  # (payload array byte)
34166     0x11/imm32/alloc-id:fake:payload
34167     # "loop-if-="
34168     0x9/imm32/size
34169     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
34170 _string-loop-if->:  # (payload array byte)
34171     0x11/imm32/alloc-id:fake:payload
34172     # "loop-if->"
34173     0x9/imm32/size
34174     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
34175 _string-loop-if->=:  # (payload array byte)
34176     0x11/imm32/alloc-id:fake:payload
34177     # "loop-if->="
34178     0xa/imm32/size
34179     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
34180 _string-loop-if-!=:  # (payload array byte)
34181     0x11/imm32/alloc-id:fake:payload
34182     # "loop-if-!="
34183     0xa/imm32/size
34184     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
34185 _string-loop-if-addr<:  # (payload array byte)
34186     0x11/imm32/alloc-id:fake:payload
34187     # "loop-if-addr<"
34188     0xd/imm32/size
34189     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
34190 _string-loop-if-addr<=:  # (payload array byte)
34191     0x11/imm32/alloc-id:fake:payload
34192     # "loop-if-addr<="
34193     0xe/imm32/size
34194     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
34195 _string-loop-if-addr>:  # (payload array byte)
34196     0x11/imm32/alloc-id:fake:payload
34197     # "loop-if-addr>"
34198     0xd/imm32/size
34199     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
34200 _string-loop-if-addr>=:  # (payload array byte)
34201     0x11/imm32/alloc-id:fake:payload
34202     # "loop-if-addr>="
34203     0xe/imm32/size
34204     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
34205 _string-loop-if-float<:  # (payload array byte)
34206     0x11/imm32/alloc-id:fake:payload
34207     # "loop-if-float<"
34208     0xe/imm32/size
34209     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
34210 _string-loop-if-float<=:  # (payload array byte)
34211     0x11/imm32/alloc-id:fake:payload
34212     # "loop-if-float<="
34213     0xf/imm32/size
34214     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
34215 _string-loop-if-float>:  # (payload array byte)
34216     0x11/imm32/alloc-id:fake:payload
34217     # "loop-if-float>"
34218     0xe/imm32/size
34219     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
34220 _string-loop-if-float>=:  # (payload array byte)
34221     0x11/imm32/alloc-id:fake:payload
34222     # "loop-if-float>="
34223     0xf/imm32/size
34224     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
34225 _string-loop-if-carry:  # (payload array byte)
34226     0x11/imm32/alloc-id:fake:payload
34227     # "loop-if-carry"
34228     0xd/imm32/size
34229     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34230 _string-loop-if-not-carry:  # (payload array byte)
34231     0x11/imm32/alloc-id:fake:payload
34232     # "loop-if-not-carry"
34233     0x11/imm32/size
34234     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
34235 _string-loop-if-overflow:  # (payload array byte)
34236     0x11/imm32/alloc-id:fake:payload
34237     # "loop-if-overflow"
34238     0x10/imm32/size
34239     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34240 _string-loop-if-not-overflow:  # (payload array byte)
34241     0x11/imm32/alloc-id:fake:payload
34242     # "loop-if-not-overflow"
34243     0x14/imm32/size
34244     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34245 _string-multiply:  # (payload array byte)
34246     0x11/imm32/alloc-id:fake:payload
34247     # "multiply"
34248     0x8/imm32/size
34249     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
34250 _string-convert:  # (payload array byte)
34251     0x11/imm32/alloc-id:fake:payload
34252     # "convert"
34253     0x7/imm32/size
34254     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
34255 _string-truncate:  # (payload array byte)
34256     0x11/imm32/alloc-id:fake:payload
34257     # "truncate"
34258     0x8/imm32/size
34259     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
34260 _string-reinterpret:  # (payload array byte)
34261     0x11/imm32/alloc-id:fake:payload
34262     # "reinterpret"
34263     0xb/imm32/size
34264     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
34265 _string-divide:
34266     0x11/imm32/alloc-id:fake:payload
34267     # "divide"
34268     0x6/imm32/size
34269     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
34270 _string-max:
34271     0x11/imm32/alloc-id:fake:payload
34272     # "max"
34273     0x3/imm32/size
34274     0x6d/m 0x61/a 0x78/x
34275 _string-min:
34276     0x11/imm32/alloc-id:fake:payload
34277     # "min"
34278     0x3/imm32/size
34279     0x6d/m 0x69/i 0x6e/n
34280 _string-reciprocal:
34281     0x11/imm32/alloc-id:fake:payload
34282     # "reciprocal"
34283     0xa/imm32/size
34284     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
34285 _string-square-root:
34286     0x11/imm32/alloc-id:fake:payload
34287     # "square-root"
34288     0xb/imm32/size
34289     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
34290 _string-inverse-square-root:
34291     0x11/imm32/alloc-id:fake:payload
34292     # "inverse-square-root"
34293     0x13/imm32/size
34294     0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
34295 _string-negate:  # (payload array byte)
34296     0x11/imm32/alloc-id:fake:payload
34297     # "negate"
34298     0x6/imm32/size
34299     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
34300 _string-not:  # (payload array byte)
34301     0x11/imm32/alloc-id:fake:payload
34302     # "not"
34303     0x3/imm32/size
34304     0x6e/n 0x6f/o 0x74/t
34305 _string-or:  # (payload array byte)
34306     0x11/imm32/alloc-id:fake:payload
34307     # "or"
34308     0x2/imm32/size
34309     0x6f/o 0x72/r
34310 _string-or-with:  # (payload array byte)
34311     0x11/imm32/alloc-id:fake:payload
34312     # "or-with"
34313     0x7/imm32/size
34314     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34315 _string-subtract:  # (payload array byte)
34316     0x11/imm32/alloc-id:fake:payload
34317     # "subtract"
34318     0x8/imm32/size
34319     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34320 _string-subtract-from:  # (payload array byte)
34321     0x11/imm32/alloc-id:fake:payload
34322     # "subtract-from"
34323     0xd/imm32/size
34324     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m
34325 _string-xor:  # (payload array byte)
34326     0x11/imm32/alloc-id:fake:payload
34327     # "xor"
34328     0x3/imm32/size
34329     0x78/x 0x6f/o 0x72/r
34330 _string-xor-with:  # (payload array byte)
34331     0x11/imm32/alloc-id:fake:payload
34332     # "xor-with"
34333     0x8/imm32/size
34334     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34335 _string-shift-left:  # (payload array byte)
34336     0x11/imm32/alloc-id:fake:payload
34337     # "shift-left"
34338     0xa/imm32/size
34339     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
34340 _string-shift-right:  # (payload array byte)
34341     0x11/imm32/alloc-id:fake:payload
34342     # "shift-right"
34343     0xb/imm32/size
34344     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
34345 _string-shift-right-signed:  # (payload array byte)
34346     0x11/imm32/alloc-id:fake:payload
34347     # "shift-right-signed"
34348     0x12/imm32/size
34349     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n 0x65/e 0x64/d
34350 
34351 # string literals for SubX instructions
34352 _string_01_add_to:  # (payload array byte)
34353     0x11/imm32/alloc-id:fake:payload
34354     # "01/add-to"
34355     0x9/imm32/size
34356     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
34357 _string_03_add:  # (payload array byte)
34358     0x11/imm32/alloc-id:fake:payload
34359     # "03/add"
34360     0x6/imm32/size
34361     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
34362 _string_05_add_to_eax:  # (payload array byte)
34363     0x11/imm32/alloc-id:fake:payload
34364     # "05/add-to-eax"
34365     0xd/imm32/size
34366     0x30/0 0x35/5 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x
34367 _string_09_or_with:  # (payload array byte)
34368     0x11/imm32/alloc-id:fake:payload
34369     # "09/or-with"
34370     0xa/imm32/size
34371     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34372 _string_0b_or:  # (payload array byte)
34373     0x11/imm32/alloc-id:fake:payload
34374     # "0b/or"
34375     0x5/imm32/size
34376     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
34377 _string_0d_or_with_eax:  # (payload array byte)
34378     0x11/imm32/alloc-id:fake:payload
34379     # "0d/or-with-eax"
34380     0xe/imm32/size
34381     0x30/0 0x64/d 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
34382 _string_0f_80_jump_label:  # (payload array byte)
34383     0x11/imm32/alloc-id:fake:payload
34384     # "0f 80/jump-if-overflow"
34385     0x16/imm32/size
34386     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34387 _string_0f_80_jump_break:  # (payload array byte)
34388     0x11/imm32/alloc-id:fake:payload
34389     # "0f 80/jump-if-overflow break/disp32"
34390     0x23/imm32/size
34391     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34392 _string_0f_80_jump_loop:  # (payload array byte)
34393     0x11/imm32/alloc-id:fake:payload
34394     # "0f 80/jump-if-overflow loop/disp32"
34395     0x22/imm32/size
34396     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34397 _string_0f_81_jump_label:  # (payload array byte)
34398     0x11/imm32/alloc-id:fake:payload
34399     # "0f 81/jump-if-not-overflow"
34400     0x1a/imm32/size
34401     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
34402 _string_0f_81_jump_break:  # (payload array byte)
34403     0x11/imm32/alloc-id:fake:payload
34404     # "0f 81/jump-if-not-overflow break/disp32"
34405     0x27/imm32/size
34406     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34407 _string_0f_81_jump_loop:  # (payload array byte)
34408     0x11/imm32/alloc-id:fake:payload
34409     # "0f 81/jump-if-not-overflow loop/disp32"
34410     0x26/imm32/size
34411     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34412 _string_0f_82_jump_label:  # (payload array byte)
34413     0x11/imm32/alloc-id:fake:payload
34414     # "0f 82/jump-if-addr<"
34415     0x13/imm32/size
34416     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
34417 _string_0f_82_jump_break:  # (payload array byte)
34418     0x11/imm32/alloc-id:fake:payload
34419     # "0f 82/jump-if-addr< break/disp32"
34420     0x20/imm32/size
34421     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34422 _string_0f_82_jump_loop:  # (payload array byte)
34423     0x11/imm32/alloc-id:fake:payload
34424     # "0f 82/jump-if-addr< loop/disp32"
34425     0x1f/imm32/size
34426     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34427 _string_0f_83_jump_label:  # (payload array byte)
34428     0x11/imm32/alloc-id:fake:payload
34429     # "0f 83/jump-if-addr>="
34430     0x14/imm32/size
34431     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
34432 _string_0f_83_jump_break:  # (payload array byte)
34433     0x11/imm32/alloc-id:fake:payload
34434     # "0f 83/jump-if-addr>= break/disp32"
34435     0x21/imm32/size
34436     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34437 _string_0f_83_jump_loop:  # (payload array byte)
34438     0x11/imm32/alloc-id:fake:payload
34439     # "0f 83/jump-if-addr>= loop/disp32"
34440     0x20/imm32/size
34441     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34442 _string_0f_84_jump_label:  # (payload array byte)
34443     0x11/imm32/alloc-id:fake:payload
34444     # "0f 84/jump-if-="
34445     0xf/imm32/size
34446     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
34447 _string_0f_84_jump_break:  # (payload array byte)
34448     0x11/imm32/alloc-id:fake:payload
34449     # "0f 84/jump-if-= break/disp32"
34450     0x1c/imm32/size
34451     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34452 _string_0f_84_jump_loop:  # (payload array byte)
34453     0x11/imm32/alloc-id:fake:payload
34454     # "0f 84/jump-if-= loop/disp32"
34455     0x1a/imm32/size
34456     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34457 _string_0f_85_jump_label:  # (payload array byte)
34458     0x11/imm32/alloc-id:fake:payload
34459     # "0f 85/jump-if-!="
34460     0x10/imm32/size
34461     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
34462 _string_0f_85_jump_break:  # (payload array byte)
34463     0x11/imm32/alloc-id:fake:payload
34464     # "0f 85/jump-if-!= break/disp32"
34465     0x1d/imm32/size
34466     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34467 _string_0f_85_jump_loop:  # (payload array byte)
34468     0x11/imm32/alloc-id:fake:payload
34469     # "0f 85/jump-if-!= loop/disp32"
34470     0x1c/imm32/size
34471     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34472 _string_0f_86_jump_label:  # (payload array byte)
34473     0x11/imm32/alloc-id:fake:payload
34474     # "0f 86/jump-if-addr<="
34475     0x14/imm32/size
34476     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
34477 _string_0f_86_jump_break:  # (payload array byte)
34478     0x11/imm32/alloc-id:fake:payload
34479     # "0f 86/jump-if-addr<= break/disp32"
34480     0x21/imm32/size
34481     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34482 _string_0f_86_jump_loop:  # (payload array byte)
34483     0x11/imm32/alloc-id:fake:payload
34484     # "0f 86/jump-if-addr<= loop/disp32"
34485     0x20/imm32/size
34486     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34487 _string_0f_87_jump_label:  # (payload array byte)
34488     0x11/imm32/alloc-id:fake:payload
34489     # "0f 87/jump-if-addr>"
34490     0x13/imm32/size
34491     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
34492 _string_0f_87_jump_break:  # (payload array byte)
34493     0x11/imm32/alloc-id:fake:payload
34494     # "0f 87/jump-if-addr> break/disp32"
34495     0x20/imm32/size
34496     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34497 _string_0f_87_jump_loop:  # (payload array byte)
34498     0x11/imm32/alloc-id:fake:payload
34499     # "0f 87/jump-if-addr> loop/disp32"
34500     0x1f/imm32/size
34501     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34502 _string_0f_8c_jump_label:  # (payload array byte)
34503     0x11/imm32/alloc-id:fake:payload
34504     # "0f 8c/jump-if-<"
34505     0xf/imm32/size
34506     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
34507 _string_0f_8c_jump_break:  # (payload array byte)
34508     0x11/imm32/alloc-id:fake:payload
34509     # "0f 8c/jump-if-< break/disp32"
34510     0x1c/imm32/size
34511     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34512 _string_0f_8c_jump_loop:  # (payload array byte)
34513     0x11/imm32/alloc-id:fake:payload
34514     # "0f 8c/jump-if-< loop/disp32"
34515     0x1b/imm32/size
34516     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34517 _string_0f_8d_jump_label:  # (payload array byte)
34518     0x11/imm32/alloc-id:fake:payload
34519     # "0f 8d/jump-if->="
34520     0x10/imm32/size
34521     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
34522 _string_0f_8d_jump_break:  # (payload array byte)
34523     0x11/imm32/alloc-id:fake:payload
34524     # "0f 8d/jump-if->= break/disp32"
34525     0x1d/imm32/size
34526     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34527 _string_0f_8d_jump_loop:  # (payload array byte)
34528     0x11/imm32/alloc-id:fake:payload
34529     # "0f 8d/jump-if->= loop/disp32"
34530     0x1c/imm32/size
34531     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34532 _string_0f_8e_jump_label:  # (payload array byte)
34533     0x11/imm32/alloc-id:fake:payload
34534     # "0f 8e/jump-if-<="
34535     0x10/imm32/size
34536     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
34537 _string_0f_8e_jump_break:  # (payload array byte)
34538     0x11/imm32/alloc-id:fake:payload
34539     # "0f 8e/jump-if-<= break/disp32"
34540     0x1d/imm32/size
34541     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34542 _string_0f_8e_jump_loop:  # (payload array byte)
34543     0x11/imm32/alloc-id:fake:payload
34544     # "0f 8e/jump-if-<= loop/disp32"
34545     0x1c/imm32/size
34546     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34547 _string_0f_8f_jump_label:  # (payload array byte)
34548     0x11/imm32/alloc-id:fake:payload
34549     # "0f 8f/jump-if->"
34550     0xf/imm32/size
34551     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
34552 _string_0f_8f_jump_break:  # (payload array byte)
34553     0x11/imm32/alloc-id:fake:payload
34554     # "0f 8f/jump-if-> break/disp32"
34555     0x1c/imm32/size
34556     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34557 _string_0f_8f_jump_loop:  # (payload array byte)
34558     0x11/imm32/alloc-id:fake:payload
34559     # "0f 8f/jump-if-> loop/disp32"
34560     0x1b/imm32/size
34561     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34562 _string_0f_af_multiply:  # (payload array byte)
34563     0x11/imm32/alloc-id:fake:payload
34564     # "0f af/multiply"
34565     0xe/imm32/size
34566     0x30/0 0x66/f 0x20/space 0x61/a 0x66/f 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
34567 _string_f3_0f_2a_convert_to_float:
34568     0x11/imm32/alloc-id:fake:payload
34569     # "f3 0f 2a/convert-to-float"
34570     0x19/imm32/size
34571     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t
34572 _string_f3_0f_2d_convert_to_int:
34573     0x11/imm32/alloc-id:fake:payload
34574     # "f3 0f 2d/convert-to-int"
34575     0x17/imm32/size
34576     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t
34577 _string_f3_0f_2c_truncate_to_int:
34578     0x11/imm32/alloc-id:fake:payload
34579     # "f3 0f 2c/truncate-to-int"
34580     0x18/imm32/size
34581     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x63/c 0x2f/slash 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t
34582 _string_f3_0f_58_add:
34583     0x11/imm32/alloc-id:fake:payload
34584     # "f3 0f 58/add"
34585     0xc/imm32/size
34586     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
34587 _string_f3_0f_5c_subtract:
34588     0x11/imm32/alloc-id:fake:payload
34589     # "f3 0f 5c/subtract"
34590     0x11/imm32/size
34591     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x63/c 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34592 _string_f3_0f_59_multiply:
34593     0x11/imm32/alloc-id:fake:payload
34594     # "f3 0f 59/multiply"
34595     0x11/imm32/size
34596     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x39/9 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
34597 _string_f3_0f_5e_divide:
34598     0x11/imm32/alloc-id:fake:payload
34599     # "f3 0f 5e/divide"
34600     0xf/imm32/size
34601     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x65/e 0x2f/slash 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
34602 _string_f3_0f_53_reciprocal:
34603     0x11/imm32/alloc-id:fake:payload
34604     # "f3 0f 53/reciprocal"
34605     0x13/imm32/size
34606     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x33/3 0x2f/slash 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
34607 _string_f3_0f_51_square_root:
34608     0x11/imm32/alloc-id:fake:payload
34609     # "f3 0f 51/square-root"
34610     0x14/imm32/size
34611     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x31/1 0x2f/slash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
34612 _string_f3_0f_52_inverse_square_root:
34613     0x11/imm32/alloc-id:fake:payload
34614     # "f3 0f 52/inverse-square-root"
34615     0x1c/imm32/size
34616     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
34617 _string_f3_0f_5d_min:
34618     0x11/imm32/alloc-id:fake:payload
34619     # "f3 0f 5d/min"
34620     0xc/imm32/size
34621     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
34622 _string_f3_0f_5f_max:
34623     0x11/imm32/alloc-id:fake:payload
34624     # "f3 0f 5f/max"
34625     0xc/imm32/size
34626     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
34627 _string_f3_0f_10_copy:
34628     0x11/imm32/alloc-id:fake:payload
34629     # "f3 0f 10/copy"
34630     0xd/imm32/size
34631     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x30/0 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
34632 _string_f3_0f_11_copy:
34633     0x11/imm32/alloc-id:fake:payload
34634     # "f3 0f 11/copy"
34635     0xd/imm32/size
34636     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x31/1 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
34637 _string_0f_2f_compare:
34638     0x11/imm32/alloc-id:fake:payload
34639     # "0f 2f/compare"
34640     0xd/imm32/size
34641     0x30/0 0x66/f 0x20/space 0x32/2 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
34642 _string_21_and_with:  # (payload array byte)
34643     0x11/imm32/alloc-id:fake:payload
34644     # "21/and-with"
34645     0xb/imm32/size
34646     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34647 _string_23_and:  # (payload array byte)
34648     0x11/imm32/alloc-id:fake:payload
34649     # "23/and"
34650     0x6/imm32/size
34651     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
34652 _string_25_and_with_eax:  # (payload array byte)
34653     0x11/imm32/alloc-id:fake:payload
34654     # "25/and-with-eax"
34655     0xf/imm32/size
34656     0x32/2 0x35/5 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
34657 _string_29_subtract_from:  # (payload array byte)
34658     0x11/imm32/alloc-id:fake:payload
34659     # "29/subtract-from"
34660     0x10/imm32/size
34661     0x32/2 0x39/9 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m
34662 _string_2b_subtract:  # (payload array byte)
34663     0x11/imm32/alloc-id:fake:payload
34664     # "2b/subtract"
34665     0xb/imm32/size
34666     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34667 _string_2d_subtract_from_eax:  # (payload array byte)
34668     0x11/imm32/alloc-id:fake:payload
34669     # "2d/subtract-from-eax"
34670     0x14/imm32/size
34671     0x32/2 0x64/d 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m 0x2d/dash 0x65/e 0x61/a 0x78/x
34672 _string_31_xor_with:  # (payload array byte)
34673     0x11/imm32/alloc-id:fake:payload
34674     # "31/xor-with"
34675     0xb/imm32/size
34676     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34677 _string_33_xor:  # (payload array byte)
34678     0x11/imm32/alloc-id:fake:payload
34679     # "33/xor"
34680     0x6/imm32/size
34681     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
34682 _string_35_xor_with_eax:  # (payload array byte)
34683     0x11/imm32/alloc-id:fake:payload
34684     # "35/xor-with-eax"
34685     0xf/imm32/size
34686     0x33/3 0x35/5 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
34687 _string_39_compare->:  # (payload array byte)
34688     0x11/imm32/alloc-id:fake:payload
34689     # "39/compare->"
34690     0xc/imm32/size
34691     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
34692 _string_3b_compare<-:  # (payload array byte)
34693     0x11/imm32/alloc-id:fake:payload
34694     # "3b/compare<-"
34695     0xc/imm32/size
34696     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
34697 _string_3d_compare_eax_with:  # (payload array byte)
34698     0x11/imm32/alloc-id:fake:payload
34699     # "3d/compare-eax-with"
34700     0x13/imm32/size
34701     0x33/3 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x65/e 0x61/a 0x78/x 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
34702 _string_40_increment_eax:  # (payload array byte)
34703     0x11/imm32/alloc-id:fake:payload
34704     # "40/increment-eax"
34705     0x10/imm32/size
34706     0x34/4 0x30/0 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x
34707 _string_41_increment_ecx:  # (payload array byte)
34708     0x11/imm32/alloc-id:fake:payload
34709     # "41/increment-ecx"
34710     0x10/imm32/size
34711     0x34/4 0x31/1 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x
34712 _string_42_increment_edx:  # (payload array byte)
34713     0x11/imm32/alloc-id:fake:payload
34714     # "42/increment-edx"
34715     0x10/imm32/size
34716     0x34/4 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x
34717 _string_43_increment_ebx:  # (payload array byte)
34718     0x11/imm32/alloc-id:fake:payload
34719     # "43/increment-ebx"
34720     0x10/imm32/size
34721     0x34/4 0x33/3 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x
34722 _string_46_increment_esi:  # (payload array byte)
34723     0x11/imm32/alloc-id:fake:payload
34724     # "46/increment-esi"
34725     0x10/imm32/size
34726     0x34/4 0x36/6 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i
34727 _string_47_increment_edi:  # (payload array byte)
34728     0x11/imm32/alloc-id:fake:payload
34729     # "47/increment-edi"
34730     0x10/imm32/size
34731     0x34/4 0x37/7 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i
34732 _string_48_decrement_eax:  # (payload array byte)
34733     0x11/imm32/alloc-id:fake:payload
34734     # "48/decrement-eax"
34735     0x10/imm32/size
34736     0x34/4 0x38/8 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x
34737 _string_49_decrement_ecx:  # (payload array byte)
34738     0x11/imm32/alloc-id:fake:payload
34739     # "49/decrement-ecx"
34740     0x10/imm32/size
34741     0x34/4 0x39/9 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x
34742 _string_4a_decrement_edx:  # (payload array byte)
34743     0x11/imm32/alloc-id:fake:payload
34744     # "4a/decrement-edx"
34745     0x10/imm32/size
34746     0x34/4 0x61/a 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x
34747 _string_4b_decrement_ebx:  # (payload array byte)
34748     0x11/imm32/alloc-id:fake:payload
34749     # "4b/decrement-ebx"
34750     0x10/imm32/size
34751     0x34/4 0x62/b 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x
34752 _string_4e_decrement_esi:  # (payload array byte)
34753     0x11/imm32/alloc-id:fake:payload
34754     # "4e/decrement-esi"
34755     0x10/imm32/size
34756     0x34/4 0x65/e 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i
34757 _string_4f_decrement_edi:  # (payload array byte)
34758     0x11/imm32/alloc-id:fake:payload
34759     # "4f/decrement-edi"
34760     0x10/imm32/size
34761     0x34/4 0x66/f 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i
34762 _string_81_subop_add:  # (payload array byte)
34763     0x11/imm32/alloc-id:fake:payload
34764     # "81 0/subop/add"
34765     0xe/imm32/size
34766     0x38/8 0x31/1 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x64/d 0x64/d
34767 _string_81_subop_or:  # (payload array byte)
34768     0x11/imm32/alloc-id:fake:payload
34769     # "81 1/subop/or"
34770     0xd/imm32/size
34771     0x38/8 0x31/1 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6f/o 0x72/r
34772 _string_81_subop_and:  # (payload array byte)
34773     0x11/imm32/alloc-id:fake:payload
34774     # "81 4/subop/and"
34775     0xe/imm32/size
34776     0x38/8 0x31/1 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x6e/n 0x64/d
34777 _string_81_subop_subtract:  # (payload array byte)
34778     0x11/imm32/alloc-id:fake:payload
34779     # "81 5/subop/subtract"
34780     0x13/imm32/size
34781     0x38/8 0x31/1 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
34782 _string_81_subop_xor:  # (payload array byte)
34783     0x11/imm32/alloc-id:fake:payload
34784     # "81 6/subop/xor"
34785     0xe/imm32/size
34786     0x38/8 0x31/1 0x20/space 0x36/6 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x78/x 0x6f/o 0x72/r
34787 _string_81_subop_compare:  # (payload array byte)
34788     0x11/imm32/alloc-id:fake:payload
34789     # "81 7/subop/compare"
34790     0x12/imm32/size
34791     0x38/8 0x31/1 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
34792 _string_89_<-:  # (payload array byte)
34793     0x11/imm32/alloc-id:fake:payload
34794     # "89/<-"
34795     0x5/imm32/size
34796     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
34797 _string_8b_->:  # (payload array byte)
34798     0x11/imm32/alloc-id:fake:payload
34799     # "8b/->"
34800     0x5/imm32/size
34801     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
34802 _string_8a_copy_byte:
34803     0x11/imm32/alloc-id:fake:payload
34804     # "8a/byte->"
34805     0x9/imm32/size
34806     0x38/8 0x61/a 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x3e/>
34807 _string_88_copy_byte:
34808     0x11/imm32/alloc-id:fake:payload
34809     # "88/byte<-"
34810     0x9/imm32/size
34811     0x38/8 0x38/8 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
34812 _string_8d_copy_address:  # (payload array byte)
34813     0x11/imm32/alloc-id:fake:payload
34814     # "8d/copy-address"
34815     0xf/imm32/size
34816     0x38/8 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
34817 _string_b8_copy_to_eax:  # (payload array byte)
34818     0x11/imm32/alloc-id:fake:payload
34819     # "b8/copy-to-eax"
34820     0xe/imm32/size
34821     0x62/b 0x38/8 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x
34822 _string_b9_copy_to_ecx:  # (payload array byte)
34823     0x11/imm32/alloc-id:fake:payload
34824     # "b9/copy-to-ecx"
34825     0xe/imm32/size
34826     0x62/b 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x63/c 0x78/x
34827 _string_ba_copy_to_edx:  # (payload array byte)
34828     0x11/imm32/alloc-id:fake:payload
34829     # "ba/copy-to-edx"
34830     0xe/imm32/size
34831     0x62/b 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x78/x
34832 _string_bb_copy_to_ebx:  # (payload array byte)
34833     0x11/imm32/alloc-id:fake:payload
34834     # "bb/copy-to-ebx"
34835     0xe/imm32/size
34836     0x62/b 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x62/b 0x78/x
34837 _string_be_copy_to_esi:  # (payload array byte)
34838     0x11/imm32/alloc-id:fake:payload
34839     # "be/copy-to-esi"
34840     0xe/imm32/size
34841     0x62/b 0x65/e 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x73/s 0x69/i
34842 _string_bf_copy_to_edi:  # (payload array byte)
34843     0x11/imm32/alloc-id:fake:payload
34844     # "bf/copy-to-edi"
34845     0xe/imm32/size
34846     0x62/b 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x69/i
34847 _string_c7_subop_copy:  # (payload array byte)
34848     0x11/imm32/alloc-id:fake:payload
34849     # "c7 0/subop/copy"
34850     0xf/imm32/size
34851     0x63/c 0x37/7 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
34852 _string_e9_jump_label:  # (payload array byte)
34853     0x11/imm32/alloc-id:fake:payload
34854     # "e9/jump"
34855     0x7/imm32/size
34856     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
34857 _string_e9_jump_break:  # (payload array byte)
34858     0x11/imm32/alloc-id:fake:payload
34859     # "e9/jump break/disp32"
34860     0x14/imm32/size
34861     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34862 _string_e9_jump_loop:  # (payload array byte)
34863     0x11/imm32/alloc-id:fake:payload
34864     # "e9/jump loop/disp32"
34865     0x13/imm32/size
34866     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
34867 _string_f7_subop_negate:
34868     0x11/imm32/alloc-id:fake:payload
34869     # "f7 3/subop/negate"
34870     0x11/imm32/size
34871     0x66/f 0x37/7 0x20/space 0x33/3 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
34872 _string_f7_subop_not:
34873     0x11/imm32/alloc-id:fake:payload
34874     # "f7 2/subop/not"
34875     0xe/imm32/size
34876     0x66/f 0x37/7 0x20/space 0x32/2 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x6f/o 0x74/t
34877 _string_ff_subop_increment:  # (payload array byte)
34878     0x11/imm32/alloc-id:fake:payload
34879     # "ff 0/subop/increment"
34880     0x14/imm32/size
34881     0x66/f 0x66/f 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
34882 _string_ff_subop_decrement:  # (payload array byte)
34883     0x11/imm32/alloc-id:fake:payload
34884     # "ff 1/subop/decrement"
34885     0x14/imm32/size
34886     0x66/f 0x66/f 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
34887 _string_c1_subop_shift_left:  # (payload array byte)
34888     0x11/imm32/alloc-id:fake:payload
34889     # "c1/shift 4/subop/left"
34890     0x15/imm32/size
34891     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6c/l 0x65/e 0x66/f 0x74/t
34892 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
34893     0x11/imm32/alloc-id:fake:payload
34894     # "c1/shift 5/subop/right-padding-zeroes"
34895     0x25/imm32/size
34896     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x61/a 0x64/d 0x64/d 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x7a/z 0x65/e 0x72/r 0x6f/o 0x65/e 0x73/s
34897 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
34898     0x11/imm32/alloc-id:fake:payload
34899     # "c1/shift 7/subop/right-preserving-sign"
34900     0x26/imm32/size
34901     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x72/r 0x65/e 0x73/s 0x65/e 0x72/r 0x76/v 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n
34902 
34903 Single-int-var-in-mem:  # (payload list var)
34904     0x11/imm32/alloc-id:fake:payload
34905     0x11/imm32/alloc-id:fake
34906     Int-var-in-mem/imm32
34907     0/imm32/next
34908     0/imm32/next
34909 
34910 Int-var-in-mem:  # (payload var)
34911     0x11/imm32/alloc-id:fake:payload
34912     0/imm32/name
34913     0/imm32/name
34914     0x11/imm32/alloc-id:fake
34915     Type-int/imm32
34916     1/imm32/some-block-depth
34917     1/imm32/some-stack-offset
34918     0/imm32/no-register
34919     0/imm32/no-register
34920 
34921 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34922 Single-byte-var-in-mem:  # (payload list var)
34923     0x11/imm32/alloc-id:fake:payload
34924     0x11/imm32/alloc-id:fake
34925     Byte-var-in-mem/imm32
34926     0/imm32/next
34927     0/imm32/next
34928 
34929 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34930 Byte-var-in-mem:  # (payload var)
34931     0x11/imm32/alloc-id:fake:payload
34932     0/imm32/name
34933     0/imm32/name
34934     0x11/imm32/alloc-id:fake
34935     Type-byte/imm32
34936     1/imm32/some-block-depth
34937     1/imm32/some-stack-offset
34938     0/imm32/no-register
34939     0/imm32/no-register
34940 
34941 Two-args-int-stack-int-reg:  # (payload list var)
34942     0x11/imm32/alloc-id:fake:payload
34943     0x11/imm32/alloc-id:fake
34944     Int-var-in-mem/imm32
34945     0x11/imm32/alloc-id:fake
34946     Single-int-var-in-some-register/imm32/next
34947 
34948 Two-int-args-in-regs:  # (payload list var)
34949     0x11/imm32/alloc-id:fake:payload
34950     0x11/imm32/alloc-id:fake
34951     Int-var-in-some-register/imm32
34952     0x11/imm32/alloc-id:fake
34953     Single-int-var-in-some-register/imm32/next
34954 
34955 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
34956 Two-args-byte-stack-byte-reg:  # (payload list var)
34957     0x11/imm32/alloc-id:fake:payload
34958     0x11/imm32/alloc-id:fake
34959     Byte-var-in-mem/imm32
34960     0x11/imm32/alloc-id:fake
34961     Single-byte-var-in-some-register/imm32/next
34962 
34963 Two-args-int-reg-int-stack:  # (payload list var)
34964     0x11/imm32/alloc-id:fake:payload
34965     0x11/imm32/alloc-id:fake
34966     Int-var-in-some-register/imm32
34967     0x11/imm32/alloc-id:fake
34968     Single-int-var-in-mem/imm32/next
34969 
34970 Two-args-int-eax-int-literal:  # (payload list var)
34971     0x11/imm32/alloc-id:fake:payload
34972     0x11/imm32/alloc-id:fake
34973     Int-var-in-eax/imm32
34974     0x11/imm32/alloc-id:fake
34975     Single-lit-var/imm32/next
34976 
34977 Int-var-and-literal:  # (payload list var)
34978     0x11/imm32/alloc-id:fake:payload
34979     0x11/imm32/alloc-id:fake
34980     Int-var-in-mem/imm32
34981     0x11/imm32/alloc-id:fake
34982     Single-lit-var/imm32/next
34983 
34984 Int-var-in-register-and-literal:  # (payload list var)
34985     0x11/imm32/alloc-id:fake:payload
34986     0x11/imm32/alloc-id:fake
34987     Int-var-in-some-register/imm32
34988     0x11/imm32/alloc-id:fake
34989     Single-lit-var/imm32/next
34990 
34991 Two-float-args-in-regs:  # (payload list var)
34992     0x11/imm32/alloc-id:fake:payload
34993     0x11/imm32/alloc-id:fake
34994     Float-var-in-some-register/imm32
34995     0x11/imm32/alloc-id:fake
34996     Single-float-var-in-some-register/imm32/next
34997 
34998 Two-args-float-reg-float-stack:  # (payload list var)
34999     0x11/imm32/alloc-id:fake:payload
35000     0x11/imm32/alloc-id:fake
35001     Float-var-in-some-register/imm32
35002     0x11/imm32/alloc-id:fake
35003     Single-float-var-in-mem/imm32/next
35004 
35005 Two-args-float-stack-float-reg:  # (payload list var)
35006     0x11/imm32/alloc-id:fake:payload
35007     0x11/imm32/alloc-id:fake
35008     Float-var-in-mem/imm32
35009     0x11/imm32/alloc-id:fake
35010     Single-float-var-in-some-register/imm32/next
35011 
35012 Single-int-var-in-some-register:  # (payload list var)
35013     0x11/imm32/alloc-id:fake:payload
35014     0x11/imm32/alloc-id:fake
35015     Int-var-in-some-register/imm32
35016     0/imm32/next
35017     0/imm32/next
35018 
35019 Single-addr-var-in-some-register:  # (payload list var)
35020     0x11/imm32/alloc-id:fake:payload
35021     0x11/imm32/alloc-id:fake
35022     Addr-var-in-some-register/imm32
35023     0/imm32/next
35024     0/imm32/next
35025 
35026 Single-byte-var-in-some-register:  # (payload list var)
35027     0x11/imm32/alloc-id:fake:payload
35028     0x11/imm32/alloc-id:fake
35029     Byte-var-in-some-register/imm32
35030     0/imm32/next
35031     0/imm32/next
35032 
35033 Int-var-in-some-register:  # (payload var)
35034     0x11/imm32/alloc-id:fake:payload
35035     0/imm32/name
35036     0/imm32/name
35037     0x11/imm32/alloc-id:fake
35038     Type-int/imm32
35039     1/imm32/some-block-depth
35040     0/imm32/no-stack-offset
35041     0x11/imm32/alloc-id:fake
35042     Any-register/imm32
35043 
35044 Any-register:  # (payload array byte)
35045     0x11/imm32/alloc-id:fake:payload
35046     1/imm32/size
35047     # data
35048     2a/asterisk
35049 
35050 Addr-var-in-some-register:  # (payload var)
35051     0x11/imm32/alloc-id:fake:payload
35052     0/imm32/name
35053     0/imm32/name
35054     0x11/imm32/alloc-id:fake
35055     Type-addr/imm32
35056     1/imm32/some-block-depth
35057     0/imm32/no-stack-offset
35058     0x11/imm32/alloc-id:fake
35059     Any-register/imm32
35060 
35061 Byte-var-in-some-register:  # (payload var)
35062     0x11/imm32/alloc-id:fake:payload
35063     0/imm32/name
35064     0/imm32/name
35065     0x11/imm32/alloc-id:fake
35066     Type-byte/imm32
35067     1/imm32/some-block-depth
35068     0/imm32/no-stack-offset
35069     0x11/imm32/alloc-id:fake
35070     Any-register/imm32
35071 
35072 Single-int-var-in-eax:  # (payload list var)
35073     0x11/imm32/alloc-id:fake:payload
35074     0x11/imm32/alloc-id:fake
35075     Int-var-in-eax/imm32
35076     0/imm32/next
35077     0/imm32/next
35078 
35079 Int-var-in-eax:
35080     0x11/imm32/alloc-id:fake:payload
35081     0/imm32/name
35082     0/imm32/name
35083     0x11/imm32/alloc-id:fake
35084     Type-int/imm32
35085     1/imm32/some-block-depth
35086     0/imm32/no-stack-offset
35087     0x11/imm32/alloc-id:fake
35088     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
35089 
35090 Single-int-var-in-ecx:  # (payload list var)
35091     0x11/imm32/alloc-id:fake:payload
35092     0x11/imm32/alloc-id:fake
35093     Int-var-in-ecx/imm32
35094     0/imm32/next
35095     0/imm32/next
35096 
35097 Int-var-in-ecx:
35098     0x11/imm32/alloc-id:fake:payload
35099     0/imm32/name
35100     0/imm32/name
35101     0x11/imm32/alloc-id:fake
35102     Type-int/imm32
35103     1/imm32/some-block-depth
35104     0/imm32/no-stack-offset
35105     0x11/imm32/alloc-id:fake
35106     $Register-ecx/imm32/register
35107 
35108 Single-int-var-in-edx:  # (payload list var)
35109     0x11/imm32/alloc-id:fake:payload
35110     0x11/imm32/alloc-id:fake
35111     Int-var-in-edx/imm32
35112     0/imm32/next
35113     0/imm32/next
35114 
35115 Int-var-in-edx:  # (payload list var)
35116     0x11/imm32/alloc-id:fake:payload
35117     0/imm32/name
35118     0/imm32/name
35119     0x11/imm32/alloc-id:fake
35120     Type-int/imm32
35121     1/imm32/some-block-depth
35122     0/imm32/no-stack-offset
35123     0x11/imm32/alloc-id:fake
35124     $Register-edx/imm32/register
35125 
35126 Single-int-var-in-ebx:  # (payload list var)
35127     0x11/imm32/alloc-id:fake:payload
35128     0x11/imm32/alloc-id:fake
35129     Int-var-in-ebx/imm32
35130     0/imm32/next
35131     0/imm32/next
35132 
35133 Int-var-in-ebx:  # (payload list var)
35134     0x11/imm32/alloc-id:fake:payload
35135     0/imm32/name
35136     0/imm32/name
35137     0x11/imm32/alloc-id:fake
35138     Type-int/imm32
35139     1/imm32/some-block-depth
35140     0/imm32/no-stack-offset
35141     0x11/imm32/alloc-id:fake
35142     $Register-ebx/imm32/register
35143 
35144 Single-int-var-in-esi:  # (payload list var)
35145     0x11/imm32/alloc-id:fake:payload
35146     0x11/imm32/alloc-id:fake
35147     Int-var-in-esi/imm32
35148     0/imm32/next
35149     0/imm32/next
35150 
35151 Int-var-in-esi:  # (payload list var)
35152     0x11/imm32/alloc-id:fake:payload
35153     0/imm32/name
35154     0/imm32/name
35155     0x11/imm32/alloc-id:fake
35156     Type-int/imm32
35157     1/imm32/some-block-depth
35158     0/imm32/no-stack-offset
35159     0x11/imm32/alloc-id:fake
35160     $Register-esi/imm32/register
35161 
35162 Single-int-var-in-edi:  # (payload list var)
35163     0x11/imm32/alloc-id:fake:payload
35164     0x11/imm32/alloc-id:fake
35165     Int-var-in-edi/imm32
35166     0/imm32/next
35167     0/imm32/next
35168 
35169 Int-var-in-edi:  # (payload list var)
35170     0x11/imm32/alloc-id:fake:payload
35171     0/imm32/name
35172     0/imm32/name
35173     0x11/imm32/alloc-id:fake
35174     Type-int/imm32
35175     1/imm32/some-block-depth
35176     0/imm32/no-stack-offset
35177     0x11/imm32/alloc-id:fake
35178     $Register-edi/imm32/register
35179 
35180 Single-lit-var:  # (payload list var)
35181     0x11/imm32/alloc-id:fake:payload
35182     0x11/imm32/alloc-id:fake
35183     Lit-var/imm32
35184     0/imm32/next
35185     0/imm32/next
35186 
35187 Lit-var:  # (payload var)
35188     0x11/imm32/alloc-id:fake:payload
35189     0/imm32/name
35190     0/imm32/name
35191     0x11/imm32/alloc-id:fake
35192     Type-literal/imm32
35193     1/imm32/some-block-depth
35194     0/imm32/no-stack-offset
35195     0/imm32/no-register
35196     0/imm32/no-register
35197 
35198 Single-float-var-in-mem:  # (payload list var)
35199     0x11/imm32/alloc-id:fake:payload
35200     0x11/imm32/alloc-id:fake
35201     Float-var-in-mem/imm32
35202     0/imm32/next
35203     0/imm32/next
35204 
35205 Float-var-in-mem:  # (payload var)
35206     0x11/imm32/alloc-id:fake:payload
35207     0/imm32/name
35208     0/imm32/name
35209     0x11/imm32/alloc-id:fake
35210     Type-float/imm32
35211     1/imm32/some-block-depth
35212     1/imm32/some-stack-offset
35213     0/imm32/no-register
35214     0/imm32/no-register
35215 
35216 Single-float-var-in-some-register:  # (payload list var)
35217     0x11/imm32/alloc-id:fake:payload
35218     0x11/imm32/alloc-id:fake
35219     Float-var-in-some-register/imm32
35220     0/imm32/next
35221     0/imm32/next
35222 
35223 Float-var-in-some-register:  # (payload var)
35224     0x11/imm32/alloc-id:fake:payload
35225     0/imm32/name
35226     0/imm32/name
35227     0x11/imm32/alloc-id:fake
35228     Type-float/imm32
35229     1/imm32/some-block-depth
35230     0/imm32/no-stack-offset
35231     0x11/imm32/alloc-id:fake
35232     Any-register/imm32
35233 
35234 Type-int:  # (payload type-tree)
35235     0x11/imm32/alloc-id:fake:payload
35236     1/imm32/is-atom
35237     1/imm32/value:int
35238     0/imm32/left:unused
35239     0/imm32/right:null
35240     0/imm32/right:null
35241 
35242 Type-literal:  # (payload type-tree)
35243     0x11/imm32/alloc-id:fake:payload
35244     1/imm32/is-atom
35245     0/imm32/value:literal
35246     0/imm32/left:unused
35247     0/imm32/right:null
35248     0/imm32/right:null
35249 
35250 Type-addr:  # (payload type-tree)
35251     0x11/imm32/alloc-id:fake:payload
35252     1/imm32/is-atom
35253     2/imm32/value:addr
35254     0/imm32/left:unused
35255     0/imm32/right:null
35256     0/imm32/right:null
35257 
35258 Type-byte:  # (payload type-tree)
35259     0x11/imm32/alloc-id:fake:payload
35260     1/imm32/is-atom
35261     8/imm32/value:byte
35262     0/imm32/left:unused
35263     0/imm32/right:null
35264     0/imm32/right:null
35265 
35266 Type-float:  # (payload type-tree)
35267     0x11/imm32/alloc-id:fake:payload
35268     1/imm32/is-atom
35269     0xf/imm32/value:float
35270     0/imm32/left:unused
35271     0/imm32/right:null
35272     0/imm32/right:null
35273 
35274 == code
35275 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
35276     # . prologue
35277     55/push-ebp
35278     89/<- %ebp 4/r32/esp
35279     # . save registers
35280     50/push-eax
35281     51/push-ecx
35282     # ecx = primitive
35283     8b/-> *(ebp+0x10) 1/r32/ecx
35284     # emit primitive name
35285     (emit-indent *(ebp+8) *Curr-block-depth)
35286     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
35287     (write-buffered *(ebp+8) %eax)
35288     # emit rm32 if necessary
35289     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
35290     # emit xm32 if necessary
35291     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
35292     # emit r32 if necessary
35293     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
35294     # emit x32 if necessary
35295     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
35296     # emit imm32 if necessary
35297     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
35298     # emit imm8 if necessary
35299     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
35300     # emit disp32 if necessary
35301     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
35302     (write-buffered *(ebp+8) Newline)
35303 $emit-subx-primitive:end:
35304     # . restore registers
35305     59/pop-to-ecx
35306     58/pop-to-eax
35307     # . epilogue
35308     89/<- %esp 5/r32/ebp
35309     5d/pop-to-ebp
35310     c3/return
35311 
35312 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
35313     # . prologue
35314     55/push-ebp
35315     89/<- %ebp 4/r32/esp
35316     # . save registers
35317     50/push-eax
35318     # if (l == 0) return
35319     81 7/subop/compare *(ebp+0xc) 0/imm32
35320     74/jump-if-= $emit-subx-rm32:end/disp8
35321     # var v/eax: (addr stmt-var)
35322     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
35323     (emit-subx-var-as-rm32 *(ebp+8) %eax)
35324 $emit-subx-rm32:end:
35325     # . restore registers
35326     58/pop-to-eax
35327     # . epilogue
35328     89/<- %esp 5/r32/ebp
35329     5d/pop-to-ebp
35330     c3/return
35331 
35332 get-stmt-operand-from-arg-location:  # stmt: (addr stmt), l: arg-location, err: (addr buffered-file), ed: (addr exit-descriptor) -> var/eax: (addr stmt-var)
35333     # . prologue
35334     55/push-ebp
35335     89/<- %ebp 4/r32/esp
35336     # . save registers
35337     51/push-ecx
35338     # eax = l
35339     8b/-> *(ebp+0xc) 0/r32/eax
35340     # ecx = stmt
35341     8b/-> *(ebp+8) 1/r32/ecx
35342     # if (l == 1) return stmt->inouts
35343     {
35344       3d/compare-eax-and 1/imm32
35345       75/jump-if-!= break/disp8
35346 $get-stmt-operand-from-arg-location:1:
35347       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35348       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35349     }
35350     # if (l == 2) return stmt->inouts->next
35351     {
35352       3d/compare-eax-and 2/imm32
35353       75/jump-if-!= break/disp8
35354 $get-stmt-operand-from-arg-location:2:
35355       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35356       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35357       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35358     }
35359     # if (l == 3) return stmt->outputs
35360     {
35361       3d/compare-eax-and 3/imm32
35362       75/jump-if-!= break/disp8
35363 $get-stmt-operand-from-arg-location:3:
35364       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35365       eb/jump $get-stmt-operand-from-arg-location:end/disp8
35366     }
35367     # abort
35368     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
35369 $get-stmt-operand-from-arg-location:end:
35370     # . restore registers
35371     59/pop-to-ecx
35372     # . epilogue
35373     89/<- %esp 5/r32/ebp
35374     5d/pop-to-ebp
35375     c3/return
35376 
35377 $get-stmt-operand-from-arg-location:abort:
35378     # error("invalid arg-location " eax)
35379     (write-buffered *(ebp+0x10) "invalid arg-location ")
35380     (write-int32-hex-buffered *(ebp+0x10) %eax)
35381     (write-buffered *(ebp+0x10) Newline)
35382     (flush *(ebp+0x10))
35383     (stop *(ebp+0x14) 1)
35384     # never gets here
35385 
35386 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35387     # . prologue
35388     55/push-ebp
35389     89/<- %ebp 4/r32/esp
35390     # . save registers
35391     50/push-eax
35392     51/push-ecx
35393     # if (l == 0) return
35394     81 7/subop/compare *(ebp+0xc) 0/imm32
35395     0f 84/jump-if-= $emit-subx-r32:end/disp32
35396     # var v/eax: (addr stmt-var)
35397     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35398     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35399     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
35400 #?     (write-buffered Stderr "looking up ")
35401 #?     (write-buffered Stderr %eax)
35402 #?     (write-buffered Stderr Newline)
35403 #?     (flush Stderr)
35404     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
35405     (write-buffered *(ebp+8) Space)
35406     (write-int32-hex-buffered *(ebp+8) *eax)
35407     (write-buffered *(ebp+8) "/r32")
35408 $emit-subx-r32:end:
35409     # . restore registers
35410     59/pop-to-ecx
35411     58/pop-to-eax
35412     # . epilogue
35413     89/<- %esp 5/r32/ebp
35414     5d/pop-to-ebp
35415     c3/return
35416 
35417 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35418     # . prologue
35419     55/push-ebp
35420     89/<- %ebp 4/r32/esp
35421     # . save registers
35422     50/push-eax
35423     51/push-ecx
35424     # if (l == 0) return
35425     81 7/subop/compare *(ebp+0xc) 0/imm32
35426     0f 84/jump-if-= $emit-subx-x32:end/disp32
35427     # var v/eax: (addr stmt-var)
35428     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35429     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35430     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
35431 #?     (write-buffered Stderr "looking up ")
35432 #?     (write-buffered Stderr %eax)
35433 #?     (write-buffered Stderr Newline)
35434 #?     (flush Stderr)
35435     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
35436     (write-buffered *(ebp+8) Space)
35437     (write-int32-hex-buffered *(ebp+8) *eax)
35438     (write-buffered *(ebp+8) "/x32")
35439 $emit-subx-x32:end:
35440     # . restore registers
35441     59/pop-to-ecx
35442     58/pop-to-eax
35443     # . epilogue
35444     89/<- %esp 5/r32/ebp
35445     5d/pop-to-ebp
35446     c3/return
35447 
35448 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35449     # . prologue
35450     55/push-ebp
35451     89/<- %ebp 4/r32/esp
35452     # . save registers
35453     50/push-eax
35454     51/push-ecx
35455     # if (l == 0) return
35456     81 7/subop/compare *(ebp+0xc) 0/imm32
35457     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35458     # var v/eax: (handle var)
35459     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35460     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35461     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35462     (write-buffered *(ebp+8) Space)
35463     (write-buffered *(ebp+8) %eax)
35464     (write-buffered *(ebp+8) "/imm32")
35465 $emit-subx-imm32:end:
35466     # . restore registers
35467     59/pop-to-ecx
35468     58/pop-to-eax
35469     # . epilogue
35470     89/<- %esp 5/r32/ebp
35471     5d/pop-to-ebp
35472     c3/return
35473 
35474 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
35475     # . prologue
35476     55/push-ebp
35477     89/<- %ebp 4/r32/esp
35478     # . save registers
35479     50/push-eax
35480     51/push-ecx
35481     # if (l == 0) return
35482     81 7/subop/compare *(ebp+0xc) 0/imm32
35483     0f 84/jump-if-= $emit-subx-imm32:end/disp32
35484     # var v/eax: (handle var)
35485     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
35486     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35487     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35488     (write-buffered *(ebp+8) Space)
35489     (write-buffered *(ebp+8) %eax)
35490     (write-buffered *(ebp+8) "/imm8")
35491 $emit-subx-imm8:end:
35492     # . restore registers
35493     59/pop-to-ecx
35494     58/pop-to-eax
35495     # . epilogue
35496     89/<- %esp 5/r32/ebp
35497     5d/pop-to-ebp
35498     c3/return
35499 
35500 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
35501     # . prologue
35502     55/push-ebp
35503     89/<- %ebp 4/r32/esp
35504     # . save registers
35505     50/push-eax
35506     51/push-ecx
35507     # if (location == 0) return
35508     81 7/subop/compare *(ebp+0xc) 0/imm32
35509     0f 84/jump-if-= $emit-subx-disp32:end/disp32
35510     # var v/eax: (addr stmt-var)
35511     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
35512     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
35513     (lookup *eax *(eax+4))  # Var-name Var-name => eax
35514     (write-buffered *(ebp+8) Space)
35515     (write-buffered *(ebp+8) %eax)
35516     # hack: if instruction operation starts with "break", emit ":break"
35517     # var name/ecx: (addr array byte) = lookup(stmt->operation)
35518     8b/-> *(ebp+0x10) 0/r32/eax
35519     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
35520     89/<- %ecx 0/r32/eax
35521     {
35522       (string-starts-with? %ecx "break")  # => eax
35523       3d/compare-eax-and 0/imm32/false
35524       74/jump-if-= break/disp8
35525       (write-buffered *(ebp+8) ":break")
35526     }
35527     # hack: if instruction operation starts with "loop", emit ":loop"
35528     {
35529       (string-starts-with? %ecx "loop")  # => eax
35530       3d/compare-eax-and 0/imm32/false
35531       74/jump-if-= break/disp8
35532       (write-buffered *(ebp+8) ":loop")
35533     }
35534     (write-buffered *(ebp+8) "/disp32")
35535 $emit-subx-disp32:end:
35536     # . restore registers
35537     59/pop-to-ecx
35538     58/pop-to-eax
35539     # . epilogue
35540     89/<- %esp 5/r32/ebp
35541     5d/pop-to-ebp
35542     c3/return
35543 
35544 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
35545     # . prologue
35546     55/push-ebp
35547     89/<- %ebp 4/r32/esp
35548     # . save registers
35549     50/push-eax
35550     51/push-ecx
35551     #
35552     (emit-indent *(ebp+8) *Curr-block-depth)
35553     (write-buffered *(ebp+8) "(")
35554     # ecx = stmt
35555     8b/-> *(ebp+0xc) 1/r32/ecx
35556     # - emit function name
35557     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35558     (write-buffered *(ebp+8) %eax)
35559     # - emit arguments
35560     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
35561     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35562     {
35563       # if (curr == null) break
35564       3d/compare-eax-and 0/imm32
35565       74/jump-if-= break/disp8
35566       #
35567       (emit-subx-call-operand *(ebp+8) %eax)
35568       # curr = lookup(curr->next)
35569       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
35570       eb/jump loop/disp8
35571     }
35572     #
35573     (write-buffered *(ebp+8) ")\n")
35574 $emit-call:end:
35575     # . restore registers
35576     59/pop-to-ecx
35577     58/pop-to-eax
35578     # . epilogue
35579     89/<- %esp 5/r32/ebp
35580     5d/pop-to-ebp
35581     c3/return
35582 
35583 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
35584     # shares code with emit-subx-var-as-rm32
35585     # . prologue
35586     55/push-ebp
35587     89/<- %ebp 4/r32/esp
35588     # . save registers
35589     50/push-eax
35590     51/push-ecx
35591     56/push-esi
35592     # ecx = s
35593     8b/-> *(ebp+0xc) 1/r32/ecx
35594     # var operand/esi: (addr var) = lookup(s->value)
35595     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35596     89/<- %esi 0/r32/eax
35597     # if (operand->register && !s->is-deref?) emit "%__"
35598     {
35599 $emit-subx-call-operand:check-for-register-direct:
35600       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35601       74/jump-if-= break/disp8
35602       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35603       75/jump-if-!= break/disp8
35604 $emit-subx-call-operand:register-direct:
35605       (write-buffered *(ebp+8) " %")
35606       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35607       (write-buffered *(ebp+8) %eax)
35608       e9/jump $emit-subx-call-operand:end/disp32
35609     }
35610     # else if (operand->register && s->is-deref?) emit "*__"
35611     {
35612 $emit-subx-call-operand:check-for-register-indirect:
35613       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35614       74/jump-if-= break/disp8
35615       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35616       74/jump-if-= break/disp8
35617 $emit-subx-call-operand:register-indirect:
35618       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
35619       e9/jump $emit-subx-call-operand:end/disp32
35620     }
35621     # else if (operand->stack-offset) emit "*(ebp+__)"
35622     {
35623       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35624       74/jump-if-= break/disp8
35625 $emit-subx-call-operand:stack:
35626       (emit-subx-call-operand-stack *(ebp+8) %esi)
35627       e9/jump $emit-subx-call-operand:end/disp32
35628     }
35629     # else if (operand->type == literal) emit "__"
35630     {
35631       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35632       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
35633       75/jump-if-!= break/disp8
35634 $emit-subx-call-operand:literal:
35635       (write-buffered *(ebp+8) Space)
35636       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35637       (write-buffered *(ebp+8) %eax)
35638       e9/jump $emit-subx-call-operand:end/disp32
35639     }
35640     # else if (operand->type == literal-string) emit "__"
35641     {
35642       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
35643       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
35644       75/jump-if-!= break/disp8
35645 $emit-subx-call-operand:literal-string:
35646       (write-buffered *(ebp+8) Space)
35647       (lookup *esi *(esi+4))  # Var-name Var-name => eax
35648       (write-buffered *(ebp+8) %eax)
35649     }
35650 $emit-subx-call-operand:end:
35651     # . restore registers
35652     5e/pop-to-esi
35653     59/pop-to-ecx
35654     58/pop-to-eax
35655     # . epilogue
35656     89/<- %esp 5/r32/ebp
35657     5d/pop-to-ebp
35658     c3/return
35659 
35660 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
35661     # . prologue
35662     55/push-ebp
35663     89/<- %ebp 4/r32/esp
35664     # . save registers
35665     50/push-eax
35666     51/push-ecx
35667     56/push-esi
35668     # esi = v
35669     8b/-> *(ebp+0xc) 6/r32/esi
35670     # var size/ecx: int = size-of-deref(v)
35671     (size-of-deref %esi)  # => eax
35672     89/<- %ecx 0/r32/eax
35673     # var reg-name/esi: (addr array byte) = lookup(v->register)
35674     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35675     89/<- %esi 0/r32/eax
35676     # TODO: assert size is a multiple of 4
35677     # var i/eax: int = 0
35678     b8/copy-to-eax 0/imm32
35679     {
35680 $emit-subx-call-operand-register-indirect:loop:
35681       # if (i >= size) break
35682       39/compare %eax 1/r32/ecx
35683       7d/jump-if->= break/disp8
35684       # emit " *(" v->register "+" i ")"
35685       (write-buffered *(ebp+8) " *(")
35686       (write-buffered *(ebp+8) %esi)
35687       (write-buffered *(ebp+8) "+")
35688       (write-int32-hex-buffered *(ebp+8) %eax)
35689       (write-buffered *(ebp+8) ")")
35690       # i += 4
35691       05/add-to-eax 4/imm32
35692       #
35693       eb/jump loop/disp8
35694     }
35695 $emit-subx-call-operand-register-indirect:end:
35696     # . restore registers
35697     5e/pop-to-esi
35698     59/pop-to-ecx
35699     58/pop-to-eax
35700     # . epilogue
35701     89/<- %esp 5/r32/ebp
35702     5d/pop-to-ebp
35703     c3/return
35704 
35705 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
35706     # . prologue
35707     55/push-ebp
35708     89/<- %ebp 4/r32/esp
35709     # . save registers
35710     50/push-eax
35711     51/push-ecx
35712     56/push-esi
35713     # esi = v
35714     8b/-> *(ebp+0xc) 6/r32/esi
35715     # var curr/ecx: int = v->offset
35716     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
35717     # var max/eax: int = v->offset + size-of(v)
35718     (size-of %esi)  # => eax
35719     # TODO: assert size is a multiple of 4
35720     01/add-to %eax 1/r32/ecx
35721     {
35722 $emit-subx-call-operand-stack:loop:
35723       # if (curr >= max) break
35724       39/compare %ecx 0/r32/eax
35725       7d/jump-if->= break/disp8
35726       # emit " *(ebp+" curr ")"
35727       (write-buffered *(ebp+8) " *(ebp+")
35728       (write-int32-hex-buffered *(ebp+8) %ecx)
35729       (write-buffered *(ebp+8) ")")
35730       # i += 4
35731       81 0/subop/add %ecx 4/imm32
35732       #
35733       eb/jump loop/disp8
35734     }
35735 $emit-subx-call-operand-stack:end:
35736     # . restore registers
35737     5e/pop-to-esi
35738     59/pop-to-ecx
35739     58/pop-to-eax
35740     # . epilogue
35741     89/<- %esp 5/r32/ebp
35742     5d/pop-to-ebp
35743     c3/return
35744 
35745 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
35746     # . prologue
35747     55/push-ebp
35748     89/<- %ebp 4/r32/esp
35749     # . save registers
35750     50/push-eax
35751     51/push-ecx
35752     56/push-esi
35753     # ecx = s
35754     8b/-> *(ebp+0xc) 1/r32/ecx
35755     # var operand/esi: (addr var) = lookup(s->value)
35756     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
35757     89/<- %esi 0/r32/eax
35758     # if (operand->register && s->is-deref?) emit "*__"
35759     {
35760 $emit-subx-var-as-rm32:check-for-register-indirect:
35761       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35762       74/jump-if-= break/disp8
35763       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35764       74/jump-if-= break/disp8
35765 $emit-subx-var-as-rm32:register-indirect:
35766       (write-buffered *(ebp+8) " *")
35767       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35768       (write-buffered *(ebp+8) %eax)
35769       e9/jump $emit-subx-var-as-rm32:end/disp32
35770     }
35771     # if (operand->register && !s->is-deref?) emit "%__"
35772     {
35773 $emit-subx-var-as-rm32:check-for-register-direct:
35774       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
35775       74/jump-if-= break/disp8
35776       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
35777       75/jump-if-!= break/disp8
35778 $emit-subx-var-as-rm32:register-direct:
35779       (write-buffered *(ebp+8) " %")
35780       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
35781       (write-buffered *(ebp+8) %eax)
35782       e9/jump $emit-subx-var-as-rm32:end/disp32
35783     }
35784     # else if (operand->stack-offset) emit "*(ebp+__)"
35785     {
35786       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
35787       74/jump-if-= break/disp8
35788 $emit-subx-var-as-rm32:stack:
35789       (write-buffered *(ebp+8) Space)
35790       (write-buffered *(ebp+8) "*(ebp+")
35791       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
35792       (write-buffered *(ebp+8) ")")
35793     }
35794 $emit-subx-var-as-rm32:end:
35795     # . restore registers
35796     5e/pop-to-esi
35797     59/pop-to-ecx
35798     58/pop-to-eax
35799     # . epilogue
35800     89/<- %esp 5/r32/ebp
35801     5d/pop-to-ebp
35802     c3/return
35803 
35804 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
35805     # . prologue
35806     55/push-ebp
35807     89/<- %ebp 4/r32/esp
35808     # . save registers
35809     51/push-ecx
35810     # var curr/ecx: (addr primitive) = primitives
35811     8b/-> *(ebp+8) 1/r32/ecx
35812     {
35813 $find-matching-primitive:loop:
35814       # if (curr == null) break
35815       81 7/subop/compare %ecx 0/imm32
35816       74/jump-if-= break/disp8
35817       # if match(curr, stmt) return curr
35818       {
35819         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
35820         3d/compare-eax-and 0/imm32/false
35821         74/jump-if-= break/disp8
35822         89/<- %eax 1/r32/ecx
35823         eb/jump $find-matching-primitive:end/disp8
35824       }
35825 $find-matching-primitive:next-primitive:
35826       # curr = curr->next
35827       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
35828       89/<- %ecx 0/r32/eax
35829       #
35830       e9/jump loop/disp32
35831     }
35832     # return null
35833     b8/copy-to-eax 0/imm32
35834 $find-matching-primitive:end:
35835     # . restore registers
35836     59/pop-to-ecx
35837     # . epilogue
35838     89/<- %esp 5/r32/ebp
35839     5d/pop-to-ebp
35840     c3/return
35841 
35842 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
35843     # A mu stmt matches a primitive if the name matches, all the inout vars
35844     # match, and all the output vars match.
35845     # Vars match if types match and registers match.
35846     # In addition, a stmt output matches a primitive's output if types match
35847     # and the primitive has a wildcard register.
35848     # . prologue
35849     55/push-ebp
35850     89/<- %ebp 4/r32/esp
35851     # . save registers
35852     51/push-ecx
35853     52/push-edx
35854     53/push-ebx
35855     56/push-esi
35856     57/push-edi
35857     # ecx = stmt
35858     8b/-> *(ebp+8) 1/r32/ecx
35859     # edx = primitive
35860     8b/-> *(ebp+0xc) 2/r32/edx
35861     {
35862 $mu-stmt-matches-primitive?:check-name:
35863       # if (primitive->name != stmt->operation) return false
35864       # . var esi: (addr array byte) = lookup(stmt->operation)
35865       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
35866       89/<- %esi 0/r32/eax
35867       # . var edi: (addr array byte) = lookup(primitive->name)
35868       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
35869 #?       (write-buffered Stderr %eax)
35870 #?       (write-buffered Stderr Newline)
35871 #?       (flush Stderr)
35872       89/<- %edi 0/r32/eax
35873       (string-equal? %esi %edi)  # => eax
35874       3d/compare-eax-and 0/imm32/false
35875       75/jump-if-!= break/disp8
35876       b8/copy-to-eax 0/imm32
35877       e9/jump $mu-stmt-matches-primitive?:end/disp32
35878     }
35879     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
35880     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
35881     89/<- %esi 0/r32/eax
35882     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
35883     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
35884     89/<- %edi 0/r32/eax
35885     {
35886 $mu-stmt-matches-primitive?:inouts-loop:
35887       # if (curr == 0 && curr2 == 0) move on to check outputs
35888       {
35889 $mu-stmt-matches-primitive?:check-both-inouts-null:
35890         81 7/subop/compare %esi 0/imm32
35891         75/jump-if-!= break/disp8
35892 $mu-stmt-matches-primitive?:stmt-inout-null:
35893         81 7/subop/compare %edi 0/imm32
35894         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
35895 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
35896         # return false
35897         b8/copy-to-eax 0/imm32/false
35898         e9/jump $mu-stmt-matches-primitive?:end/disp32
35899       }
35900       # if (curr2 == 0) return false
35901       {
35902 $mu-stmt-matches-primitive?:check-prim-inout-null:
35903         81 7/subop/compare %edi 0/imm32
35904         75/jump-if-!= break/disp8
35905 $mu-stmt-matches-primitive?:prim-inout-null:
35906         b8/copy-to-eax 0/imm32/false
35907         e9/jump $mu-stmt-matches-primitive?:end/disp32
35908       }
35909       # if (curr != curr2) return false
35910       {
35911 $mu-stmt-matches-primitive?:check-inouts-match:
35912         (lookup *edi *(edi+4))  # List-value List-value => eax
35913         (operand-matches-primitive? %esi %eax)  # => eax
35914         3d/compare-eax-and 0/imm32/false
35915         75/jump-if-!= break/disp8
35916 $mu-stmt-matches-primitive?:inouts-match:
35917         b8/copy-to-eax 0/imm32/false
35918         e9/jump $mu-stmt-matches-primitive?:end/disp32
35919       }
35920 $mu-stmt-matches-primitive?:next-inout:
35921       # curr = lookup(curr->next)
35922       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35923       89/<- %esi 0/r32/eax
35924       # curr2 = lookup(curr2->next)
35925       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35926       89/<- %edi 0/r32/eax
35927       #
35928       e9/jump loop/disp32
35929     }
35930 $mu-stmt-matches-primitive?:check-outputs:
35931     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
35932     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
35933     89/<- %esi 0/r32/eax
35934     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
35935     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
35936     89/<- %edi 0/r32/eax
35937     {
35938 $mu-stmt-matches-primitive?:outputs-loop:
35939       # if (curr == 0) return (curr2 == 0)
35940       {
35941 $mu-stmt-matches-primitive?:check-both-outputs-null:
35942         81 7/subop/compare %esi 0/imm32
35943         75/jump-if-!= break/disp8
35944         {
35945 $mu-stmt-matches-primitive?:stmt-output-null:
35946           81 7/subop/compare %edi 0/imm32
35947           75/jump-if-!= break/disp8
35948 $mu-stmt-matches-primitive?:both-outputs-null:
35949           # return true
35950           b8/copy-to-eax 1/imm32
35951           e9/jump $mu-stmt-matches-primitive?:end/disp32
35952         }
35953 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
35954         # return false
35955         b8/copy-to-eax 0/imm32
35956         e9/jump $mu-stmt-matches-primitive?:end/disp32
35957       }
35958       # if (curr2 == 0) return false
35959       {
35960 $mu-stmt-matches-primitive?:check-prim-output-null:
35961         81 7/subop/compare %edi 0/imm32
35962         75/jump-if-!= break/disp8
35963 $mu-stmt-matches-primitive?:prim-output-is-null:
35964         b8/copy-to-eax 0/imm32
35965         e9/jump $mu-stmt-matches-primitive?:end/disp32
35966       }
35967       # if (curr != curr2) return false
35968       {
35969 $mu-stmt-matches-primitive?:check-outputs-match:
35970         (lookup *edi *(edi+4))  # List-value List-value => eax
35971         (operand-matches-primitive? %esi %eax)  # => eax
35972         3d/compare-eax-and 0/imm32/false
35973         75/jump-if-!= break/disp8
35974 $mu-stmt-matches-primitive?:outputs-match:
35975         b8/copy-to-eax 0/imm32
35976         e9/jump $mu-stmt-matches-primitive?:end/disp32
35977       }
35978 $mu-stmt-matches-primitive?:next-output:
35979       # curr = lookup(curr->next)
35980       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
35981       89/<- %esi 0/r32/eax
35982       # curr2 = lookup(curr2->next)
35983       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
35984       89/<- %edi 0/r32/eax
35985       #
35986       e9/jump loop/disp32
35987     }
35988 $mu-stmt-matches-primitive?:return-true:
35989     b8/copy-to-eax 1/imm32
35990 $mu-stmt-matches-primitive?:end:
35991     # . restore registers
35992     5f/pop-to-edi
35993     5e/pop-to-esi
35994     5b/pop-to-ebx
35995     5a/pop-to-edx
35996     59/pop-to-ecx
35997     # . epilogue
35998     89/<- %esp 5/r32/ebp
35999     5d/pop-to-ebp
36000     c3/return
36001 
36002 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
36003     # . prologue
36004     55/push-ebp
36005     89/<- %ebp 4/r32/esp
36006     # . save registers
36007     51/push-ecx
36008     52/push-edx
36009     53/push-ebx
36010     56/push-esi
36011     57/push-edi
36012     # ecx = s
36013     8b/-> *(ebp+8) 1/r32/ecx
36014     # var var/esi: (addr var) = lookup(s->value)
36015     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
36016     89/<- %esi 0/r32/eax
36017     # edi = prim-var
36018     8b/-> *(ebp+0xc) 7/r32/edi
36019 $operand-matches-primitive?:check-type:
36020     # if !category-match?(var->type, prim-var->type) return false
36021     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
36022     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
36023     89/<- %ebx 0/r32/eax
36024     # . if s is deref, vtype = vtype->right
36025     {
36026       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
36027       74/jump-if-= break/disp8
36028 $operand-matches-primitive?:is-deref:
36029       # . var t/eax: (addr type)
36030       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
36031       # . if !t->is-atom? t = t->left
36032       81 7/subop/compare *eax 0/imm32/false
36033       {
36034         75/jump-if-!= break/disp8
36035         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36036       }
36037       # .
36038       89/<- %ebx 0/r32/eax
36039     }
36040     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
36041     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
36042     (subx-type-category-match? %ebx %eax)  # => eax
36043     3d/compare-eax-and 0/imm32/false
36044     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
36045     {
36046 $operand-matches-primitive?:check-register:
36047       # if prim-var is in memory and var is in register but dereference, match
36048       {
36049         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
36050         0f 85/jump-if-!= break/disp32
36051         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
36052         74/jump-if-= break/disp8
36053         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
36054         74/jump-if-= break/disp8
36055 $operand-matches-primitive?:var-deref-match:
36056         e9/jump $operand-matches-primitive?:return-true/disp32
36057       }
36058       # if prim-var is in register and var is in register but dereference, no match
36059       {
36060         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
36061         0f 84/jump-if-= break/disp32
36062         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
36063         0f 84/jump-if-= break/disp32
36064         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
36065         74/jump-if-= break/disp8
36066 $operand-matches-primitive?:var-deref-no-match:
36067         e9/jump $operand-matches-primitive?:return-false/disp32
36068       }
36069       # return false if var->register doesn't match prim-var->register
36070       {
36071         # if register addresses are equal, it's a match
36072         # var vreg/ebx: (addr array byte) = lookup(var->register)
36073         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
36074         89/<- %ebx 0/r32/eax
36075         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
36076         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
36077         89/<- %ecx 0/r32/eax
36078         # if (vreg == preg) break
36079         39/compare %ecx 3/r32/ebx
36080         74/jump-if-= break/disp8
36081 $operand-matches-primitive?:var-register-no-match:
36082         # if either address is 0, return false
36083         81 7/subop/compare %ebx 0/imm32
36084         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
36085         81 7/subop/compare %ecx 0/imm32
36086         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
36087         # if prim-var->register is wildcard, it's a match
36088         (string-equal? %ecx "*")  # Any-register => eax
36089         3d/compare-eax-and 0/imm32/false
36090         75/jump-if-!= break/disp8
36091 $operand-matches-primitive?:wildcard-no-match:
36092         # if string contents aren't equal, return false
36093         (string-equal? %ecx %ebx)  # => eax
36094         3d/compare-eax-and 0/imm32/false
36095         74/jump-if-= $operand-matches-primitive?:return-false/disp8
36096       }
36097     }
36098 $operand-matches-primitive?:return-true:
36099     b8/copy-to-eax 1/imm32/true
36100     eb/jump $operand-matches-primitive?:end/disp8
36101 $operand-matches-primitive?:return-false:
36102     b8/copy-to-eax 0/imm32/false
36103 $operand-matches-primitive?:end:
36104     # . restore registers
36105     5f/pop-to-edi
36106     5e/pop-to-esi
36107     5b/pop-to-ebx
36108     5a/pop-to-edx
36109     59/pop-to-ecx
36110     # . epilogue
36111     89/<- %esp 5/r32/ebp
36112     5d/pop-to-ebp
36113     c3/return
36114 
36115 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
36116     # . prologue
36117     55/push-ebp
36118     89/<- %ebp 4/r32/esp
36119     # . save registers
36120     51/push-ecx
36121     # var curr/ecx: (handle function) = functions
36122     8b/-> *(ebp+8) 1/r32/ecx
36123     {
36124       # if (curr == null) break
36125       81 7/subop/compare %ecx 0/imm32
36126       74/jump-if-= break/disp8
36127 #?       (write-buffered Stderr "iter\n")
36128 #?       (flush Stderr)
36129       # if match(stmt, curr) return curr
36130       {
36131         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
36132         3d/compare-eax-and 0/imm32/false
36133         74/jump-if-= break/disp8
36134         89/<- %eax 1/r32/ecx
36135         eb/jump $find-matching-function:end/disp8
36136       }
36137       # curr = curr->next
36138       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
36139       89/<- %ecx 0/r32/eax
36140       #
36141       eb/jump loop/disp8
36142     }
36143     # return null
36144     b8/copy-to-eax 0/imm32
36145 $find-matching-function:end:
36146     # . restore registers
36147     59/pop-to-ecx
36148     # . epilogue
36149     89/<- %esp 5/r32/ebp
36150     5d/pop-to-ebp
36151     c3/return
36152 
36153 # Just compare names; user-defined functions don't support overloading yet.
36154 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
36155     # . prologue
36156     55/push-ebp
36157     89/<- %ebp 4/r32/esp
36158     # . save registers
36159     51/push-ecx
36160     # return function->name == stmt->operation
36161     # ecx = lookup(stmt->operation)
36162     8b/-> *(ebp+8) 0/r32/eax
36163     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
36164     89/<- %ecx 0/r32/eax
36165     # eax = lookup(function->name)
36166     8b/-> *(ebp+0xc) 0/r32/eax
36167     (lookup *eax *(eax+4))  # Function-name Function-name => eax
36168     (string-equal? %eax %ecx)  # => eax
36169 $mu-stmt-matches-function?:end:
36170     # . restore registers
36171     59/pop-to-ecx
36172     # . epilogue
36173     89/<- %esp 5/r32/ebp
36174     5d/pop-to-ebp
36175     c3/return
36176 
36177 # Type-checking happens elsewhere. This method is for selecting between
36178 # primitives.
36179 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
36180     # . prologue
36181     55/push-ebp
36182     89/<- %ebp 4/r32/esp
36183     # . save registers
36184     51/push-ecx
36185     # var cata/ecx: int = type-category(a)
36186     (type-category *(ebp+8))  # => eax
36187     89/<- %ecx 0/r32/eax
36188     # var catb/eax: int = type-category(b)
36189     (type-category *(ebp+0xc))  # => eax
36190     # return cata == catb
36191     39/compare %eax 1/r32/ecx
36192     0f 94/set-byte-if-= %al
36193     25/and-eax-with 0xff/imm32
36194 $subx-type-category-match?:end:
36195     # . restore registers
36196     59/pop-to-ecx
36197     # . epilogue
36198     89/<- %esp 5/r32/ebp
36199     5d/pop-to-ebp
36200     c3/return
36201 
36202 type-category:  # a: (addr type-tree) -> result/eax: int
36203     # . prologue
36204     55/push-ebp
36205     89/<- %ebp 4/r32/esp
36206     # . save registers
36207     51/push-ecx
36208     # var lit?/ecx: boolean = literal-type?(a)
36209     (simple-mu-type? *(ebp+8) 0)  # literal => eax
36210     89/<- %ecx 0/r32/eax
36211     # var float?/eax: int = float?(a)
36212     (simple-mu-type? *(ebp+8) 0xf)  # => eax
36213     # set bits for lit? and float?
36214     c1/shift 4/subop/left %ecx 1/imm8
36215     09/or %eax 1/r32/ecx
36216 $type-category:end:
36217     # . restore registers
36218     59/pop-to-ecx
36219     # . epilogue
36220     89/<- %esp 5/r32/ebp
36221     5d/pop-to-ebp
36222     c3/return
36223 
36224 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
36225     # . prologue
36226     55/push-ebp
36227     89/<- %ebp 4/r32/esp
36228     # . save registers
36229     51/push-ecx
36230     # ecx = n
36231     8b/-> *(ebp+0xc) 1/r32/ecx
36232     # return (a->value == n)
36233     8b/-> *(ebp+8) 0/r32/eax
36234     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
36235     0f 94/set-byte-if-= %al
36236     25/and-eax-with 0xff/imm32
36237 $simple-mu-type?:end:
36238     # . restore registers
36239     59/pop-to-ecx
36240     # . epilogue
36241     89/<- %esp 5/r32/ebp
36242     5d/pop-to-ebp
36243     c3/return
36244 
36245 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
36246     # . prologue
36247     55/push-ebp
36248     89/<- %ebp 4/r32/esp
36249     # eax = a
36250     8b/-> *(ebp+8) 0/r32/eax
36251     # if (!a->is-atom?) a = a->left
36252     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36253     {
36254       75/jump-if-!= break/disp8
36255       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36256     }
36257     # return (a->value == addr)
36258     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
36259     0f 94/set-byte-if-= %al
36260     25/and-eax-with 0xff/imm32
36261 $mu-addr-type?:end:
36262     # . epilogue
36263     89/<- %esp 5/r32/ebp
36264     5d/pop-to-ebp
36265     c3/return
36266 
36267 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
36268     # . prologue
36269     55/push-ebp
36270     89/<- %ebp 4/r32/esp
36271     # eax = a
36272     8b/-> *(ebp+8) 0/r32/eax
36273     # if (!a->is-atom?) a = a->left
36274     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36275     {
36276       75/jump-if-!= break/disp8
36277       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36278     }
36279     # return (a->value == array)
36280     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
36281     0f 94/set-byte-if-= %al
36282     25/and-eax-with 0xff/imm32
36283 $mu-array-type?:end:
36284     # . epilogue
36285     89/<- %esp 5/r32/ebp
36286     5d/pop-to-ebp
36287     c3/return
36288 
36289 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
36290     # . prologue
36291     55/push-ebp
36292     89/<- %ebp 4/r32/esp
36293     # . save registers
36294     56/push-esi
36295     # esi = a
36296     8b/-> *(ebp+8) 6/r32/esi
36297     # if (a->is-atom?) return false
36298     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
36299     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
36300     # if a is not an addr, return false
36301     (mu-addr-type? %esi)  # => eax
36302     3d/compare-eax-with 0/imm32/false
36303     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
36304     # if a is not an array, return false
36305     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
36306     (mu-array-type? %eax)  # => eax
36307     3d/compare-eax-with 0/imm32/false
36308     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
36309     # var p/eax: (addr type-tree) = payload of a
36310     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
36311     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
36312     # if p is an atom, return false
36313     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36314     75/jump-if-!= $mu-string-type?:return-false/disp8
36315     # return (p == byte)
36316     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36317     (simple-mu-type? %eax 8)  # byte => eax
36318     eb/jump $mu-string-type?:end/disp8
36319 $mu-string-type?:return-false:
36320     b8/copy-to-eax 0/imm32/false
36321 $mu-string-type?:end:
36322     # . restore registers
36323     5e/pop-to-esi
36324     # . epilogue
36325     89/<- %esp 5/r32/ebp
36326     5d/pop-to-ebp
36327     c3/return
36328 
36329 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
36330     # . prologue
36331     55/push-ebp
36332     89/<- %ebp 4/r32/esp
36333     # eax = a
36334     8b/-> *(ebp+8) 0/r32/eax
36335     # if (!a->is-atom?) a = a->left
36336     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
36337     {
36338       75/jump-if-!= break/disp8
36339       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
36340     }
36341     # return (a->value == stream)
36342     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
36343     0f 94/set-byte-if-= %al
36344     25/and-eax-with 0xff/imm32
36345 $mu-stream-type?:end:
36346     # . epilogue
36347     89/<- %esp 5/r32/ebp
36348     5d/pop-to-ebp
36349     c3/return
36350 
36351 test-emit-subx-stmt-primitive:
36352     # Primitive operation on a variable on the stack.
36353     #   increment foo
36354     # =>
36355     #   ff 0/subop/increment *(ebp-8)
36356     #
36357     # There's a variable on the var stack as follows:
36358     #   name: 'foo'
36359     #   type: int
36360     #   stack-offset: -8
36361     #
36362     # There's a primitive with this info:
36363     #   name: 'increment'
36364     #   inouts: int/mem
36365     #   value: 'ff 0/subop/increment'
36366     #
36367     # . prologue
36368     55/push-ebp
36369     89/<- %ebp 4/r32/esp
36370     # setup
36371     (clear-stream _test-output-stream)
36372     (clear-stream $_test-output-buffered-file->buffer)
36373     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
36374 $test-emit-subx-stmt-primitive:initialize-type:
36375     # var type/ecx: (payload type-tree) = int
36376     68/push 0/imm32/right:null
36377     68/push 0/imm32/right:null
36378     68/push 0/imm32/left:unused
36379     68/push 1/imm32/value:int
36380     68/push 1/imm32/is-atom?:true
36381     68/push 0x11/imm32/alloc-id:fake:payload
36382     89/<- %ecx 4/r32/esp
36383 $test-emit-subx-stmt-primitive:initialize-var:
36384     # var var-foo/ecx: (payload var) = var(type)
36385     68/push 0/imm32/no-register
36386     68/push 0/imm32/no-register
36387     68/push -8/imm32/stack-offset
36388     68/push 1/imm32/block-depth
36389     51/push-ecx/type
36390     68/push 0x11/imm32/alloc-id:fake
36391     68/push 0/imm32/name
36392     68/push 0/imm32/name
36393     68/push 0x11/imm32/alloc-id:fake:payload
36394     89/<- %ecx 4/r32/esp
36395 $test-emit-subx-stmt-primitive:initialize-var-name:
36396     # var-foo->name = "foo"
36397     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36398     (copy-array Heap "foo" %eax)
36399 $test-emit-subx-stmt-primitive:initialize-stmt-var:
36400     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
36401     68/push 0/imm32/is-deref:false
36402     68/push 0/imm32/next
36403     68/push 0/imm32/next
36404     51/push-ecx/var-foo
36405     68/push 0x11/imm32/alloc-id:fake
36406     68/push 0x11/imm32/alloc-id:fake:payload
36407     89/<- %ebx 4/r32/esp
36408 $test-emit-subx-stmt-primitive:initialize-stmt:
36409     # var stmt/esi: (addr statement)
36410     68/push 0/imm32/no-outputs
36411     68/push 0/imm32/no-outputs
36412     53/push-ebx/inouts
36413     68/push 0x11/imm32/alloc-id:fake
36414     68/push 0/imm32/operation
36415     68/push 0/imm32/operation
36416     68/push 1/imm32/tag
36417     89/<- %esi 4/r32/esp
36418 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
36419     # stmt->operation = "increment"
36420     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36421     (copy-array Heap "increment" %eax)
36422 $test-emit-subx-stmt-primitive:initialize-primitive:
36423     # var primitives/ebx: (addr primitive)
36424     68/push 0/imm32/next
36425     68/push 0/imm32/next
36426     68/push 0/imm32/no-x32
36427     68/push 0/imm32/no-xm32
36428     68/push 0/imm32/no-disp32
36429     68/push 0/imm32/no-imm8
36430     68/push 0/imm32/no-imm32
36431     68/push 0/imm32/no-r32
36432     68/push 1/imm32/rm32-is-first-inout
36433     68/push 0/imm32/subx-name
36434     68/push 0/imm32/subx-name
36435     68/push 0/imm32/no-outputs
36436     68/push 0/imm32/no-outputs
36437     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36438     68/push 0x11/imm32/alloc-id:fake
36439     68/push 0/imm32/name
36440     68/push 0/imm32/name
36441     89/<- %ebx 4/r32/esp
36442 $test-emit-subx-stmt-primitive:initialize-primitive-name:
36443     # primitives->name = "increment"
36444     (copy-array Heap "increment" %ebx)  # Primitive-name
36445 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
36446     # primitives->subx-name = "ff 0/subop/increment"
36447     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36448     (copy-array Heap "ff 0/subop/increment" %eax)
36449     # convert
36450     c7 0/subop/copy *Curr-block-depth 0/imm32
36451     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36452     (flush _test-output-buffered-file)
36453 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36459     # check output
36460     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
36461     # . epilogue
36462     89/<- %esp 5/r32/ebp
36463     5d/pop-to-ebp
36464     c3/return
36465 
36466 test-emit-subx-stmt-primitive-register:
36467     # Primitive operation on a variable in a register.
36468     #   foo <- increment
36469     # =>
36470     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36471     #
36472     # There's a variable on the var stack as follows:
36473     #   name: 'foo'
36474     #   type: int
36475     #   register: 'eax'
36476     #
36477     # There's a primitive with this info:
36478     #   name: 'increment'
36479     #   out: int/reg
36480     #   value: 'ff 0/subop/increment'
36481     #
36482     # . prologue
36483     55/push-ebp
36484     89/<- %ebp 4/r32/esp
36485     # setup
36486     (clear-stream _test-output-stream)
36487     (clear-stream $_test-output-buffered-file->buffer)
36488 $test-emit-subx-stmt-primitive-register:initialize-type:
36489     # var type/ecx: (payload type-tree) = int
36490     68/push 0/imm32/right:null
36491     68/push 0/imm32/right:null
36492     68/push 0/imm32/left:unused
36493     68/push 1/imm32/value:int
36494     68/push 1/imm32/is-atom?:true
36495     68/push 0x11/imm32/alloc-id:fake:payload
36496     89/<- %ecx 4/r32/esp
36497 $test-emit-subx-stmt-primitive-register:initialize-var:
36498     # var var-foo/ecx: (payload var)
36499     68/push 0/imm32/register
36500     68/push 0/imm32/register
36501     68/push 0/imm32/no-stack-offset
36502     68/push 1/imm32/block-depth
36503     51/push-ecx
36504     68/push 0x11/imm32/alloc-id:fake
36505     68/push 0/imm32/name
36506     68/push 0/imm32/name
36507     68/push 0x11/imm32/alloc-id:fake:payload
36508     89/<- %ecx 4/r32/esp
36509 $test-emit-subx-stmt-primitive-register:initialize-var-name:
36510     # var-foo->name = "foo"
36511     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36512     (copy-array Heap "foo" %eax)
36513 $test-emit-subx-stmt-primitive-register:initialize-var-register:
36514     # var-foo->register = "eax"
36515     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36516     (copy-array Heap "eax" %eax)
36517 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
36518     # var operand/ebx: (payload stmt-var)
36519     68/push 0/imm32/is-deref:false
36520     68/push 0/imm32/next
36521     68/push 0/imm32/next
36522     51/push-ecx/var-foo
36523     68/push 0x11/imm32/alloc-id:fake
36524     68/push 0x11/imm32/alloc-id:fake:payload
36525     89/<- %ebx 4/r32/esp
36526 $test-emit-subx-stmt-primitive-register:initialize-stmt:
36527     # var stmt/esi: (addr statement)
36528     53/push-ebx/outputs
36529     68/push 0x11/imm32/alloc-id:fake
36530     68/push 0/imm32/no-inouts
36531     68/push 0/imm32/no-inouts
36532     68/push 0/imm32/operation
36533     68/push 0/imm32/operation
36534     68/push 1/imm32
36535     89/<- %esi 4/r32/esp
36536 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
36537     # stmt->operation = "increment"
36538     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36539     (copy-array Heap "increment" %eax)
36540 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
36541     # var formal-var/ebx: (payload var)
36542     68/push 0/imm32/register
36543     68/push 0/imm32/register
36544     68/push 0/imm32/no-stack-offset
36545     68/push 1/imm32/block-depth
36546     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36547     68/push 0x11/imm32/alloc-id:fake
36548     68/push 0/imm32/name
36549     68/push 0/imm32/name
36550     68/push 0x11/imm32/alloc-id:fake:payload
36551     89/<- %ebx 4/r32/esp
36552 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
36553     # formal-var->name = "dummy"
36554     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36555     (copy-array Heap "dummy" %eax)
36556 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
36557     # formal-var->register = "*"
36558     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36559     (copy-array Heap "*" %eax)  # Any-register
36560 $test-emit-subx-stmt-primitive-register:initialize-var-list:
36561     # var formal-outputs/ebx: (payload list var)
36562     68/push 0/imm32/next
36563     68/push 0/imm32/next
36564     53/push-ebx/formal-var
36565     68/push 0x11/imm32/alloc-id:fake
36566     68/push 0x11/imm32/alloc-id:fake:payload
36567     89/<- %ebx 4/r32/esp
36568 $test-emit-subx-stmt-primitive-register:initialize-primitive:
36569     # var primitives/ebx: (addr primitive)
36570     68/push 0/imm32/next
36571     68/push 0/imm32/next
36572     68/push 0/imm32/no-x32
36573     68/push 0/imm32/no-xm32
36574     68/push 0/imm32/no-disp32
36575     68/push 0/imm32/no-imm8
36576     68/push 0/imm32/no-imm32
36577     68/push 0/imm32/no-r32
36578     68/push 3/imm32/rm32-is-first-output
36579     68/push 0/imm32/subx-name
36580     68/push 0/imm32/subx-name
36581     53/push-ebx/outputs
36582     68/push 0x11/imm32/alloc-id:fake
36583     68/push 0/imm32/no-inouts
36584     68/push 0/imm32/no-inouts
36585     68/push 0/imm32/name
36586     68/push 0/imm32/name
36587     89/<- %ebx 4/r32/esp
36588 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
36589     # primitives->name = "increment"
36590     (copy-array Heap "increment" %ebx)  # Primitive-name
36591 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
36592     # primitives->subx-name = "ff 0/subop/increment"
36593     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36594     (copy-array Heap "ff 0/subop/increment" %eax)
36595     # convert
36596     c7 0/subop/copy *Curr-block-depth 0/imm32
36597     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36598     (flush _test-output-buffered-file)
36599 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36605     # check output
36606     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
36607     # . epilogue
36608     89/<- %esp 5/r32/ebp
36609     5d/pop-to-ebp
36610     c3/return
36611 
36612 test-emit-subx-stmt-select-primitive:
36613     # Select the right primitive between overloads.
36614     #   foo <- increment
36615     # =>
36616     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36617     #
36618     # There's a variable on the var stack as follows:
36619     #   name: 'foo'
36620     #   type: int
36621     #   register: 'eax'
36622     #
36623     # There's two primitives, as follows:
36624     #   - name: 'increment'
36625     #     out: int/reg
36626     #     value: 'ff 0/subop/increment'
36627     #   - name: 'increment'
36628     #     inout: int/mem
36629     #     value: 'ff 0/subop/increment'
36630     #
36631     # . prologue
36632     55/push-ebp
36633     89/<- %ebp 4/r32/esp
36634     # setup
36635     (clear-stream _test-output-stream)
36636     (clear-stream $_test-output-buffered-file->buffer)
36637 $test-emit-subx-stmt-select-primitive:initialize-type:
36638     # var type/ecx: (payload type-tree) = int
36639     68/push 0/imm32/right:null
36640     68/push 0/imm32/right:null
36641     68/push 0/imm32/left:unused
36642     68/push 1/imm32/value:int
36643     68/push 1/imm32/is-atom?:true
36644     68/push 0x11/imm32/alloc-id:fake:payload
36645     89/<- %ecx 4/r32/esp
36646 $test-emit-subx-stmt-select-primitive:initialize-var:
36647     # var var-foo/ecx: (payload var)
36648     68/push 0/imm32/register
36649     68/push 0/imm32/register
36650     68/push 0/imm32/no-stack-offset
36651     68/push 1/imm32/block-depth
36652     51/push-ecx
36653     68/push 0x11/imm32/alloc-id:fake
36654     68/push 0/imm32/name
36655     68/push 0/imm32/name
36656     68/push 0x11/imm32/alloc-id:fake:payload
36657     89/<- %ecx 4/r32/esp
36658 $test-emit-subx-stmt-select-primitive:initialize-var-name:
36659     # var-foo->name = "foo"
36660     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36661     (copy-array Heap "foo" %eax)
36662 $test-emit-subx-stmt-select-primitive:initialize-var-register:
36663     # var-foo->register = "eax"
36664     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36665     (copy-array Heap "eax" %eax)
36666 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
36667     # var operand/ebx: (payload stmt-var)
36668     68/push 0/imm32/is-deref:false
36669     68/push 0/imm32/next
36670     68/push 0/imm32/next
36671     51/push-ecx/var-foo
36672     68/push 0x11/imm32/alloc-id:fake
36673     68/push 0x11/imm32/alloc-id:fake:payload
36674     89/<- %ebx 4/r32/esp
36675 $test-emit-subx-stmt-select-primitive:initialize-stmt:
36676     # var stmt/esi: (addr statement)
36677     53/push-ebx/outputs
36678     68/push 0x11/imm32/alloc-id:fake
36679     68/push 0/imm32/no-inouts
36680     68/push 0/imm32/no-inouts
36681     68/push 0/imm32/operation
36682     68/push 0/imm32/operation
36683     68/push 1/imm32
36684     89/<- %esi 4/r32/esp
36685 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
36686     # stmt->operation = "increment"
36687     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36688     (copy-array Heap "increment" %eax)
36689 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
36690     # var formal-var/ebx: (payload var)
36691     68/push 0/imm32/register
36692     68/push 0/imm32/register
36693     68/push 0/imm32/no-stack-offset
36694     68/push 1/imm32/block-depth
36695     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36696     68/push 0x11/imm32/alloc-id:fake
36697     68/push 0/imm32/name
36698     68/push 0/imm32/name
36699     68/push 0x11/imm32/alloc-id:fake:payload
36700     89/<- %ebx 4/r32/esp
36701 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
36702     # formal-var->name = "dummy"
36703     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36704     (copy-array Heap "dummy" %eax)
36705 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
36706     # formal-var->register = "*"
36707     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36708     (copy-array Heap "*" %eax)  # Any-register
36709 $test-emit-subx-stmt-select-primitive:initialize-var-list:
36710     # var formal-outputs/ebx: (payload list var)
36711     68/push 0/imm32/next
36712     68/push 0/imm32/next
36713     53/push-ebx/formal-var
36714     68/push 0x11/imm32/alloc-id:fake
36715     68/push 0x11/imm32/alloc-id:fake:payload
36716     89/<- %ebx 4/r32/esp
36717 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
36718     # var primitive2/edi: (payload primitive)
36719     68/push 0/imm32/next
36720     68/push 0/imm32/next
36721     68/push 0/imm32/no-x32
36722     68/push 0/imm32/no-xm32
36723     68/push 0/imm32/no-disp32
36724     68/push 0/imm32/no-imm8
36725     68/push 0/imm32/no-imm32
36726     68/push 0/imm32/no-r32
36727     68/push 3/imm32/rm32-is-first-output
36728     68/push 0/imm32/subx-name
36729     68/push 0/imm32/subx-name
36730     53/push-ebx/outputs
36731     68/push 0x11/imm32/alloc-id:fake
36732     68/push 0/imm32/no-inouts
36733     68/push 0/imm32/no-inouts
36734     68/push 0/imm32/name
36735     68/push 0/imm32/name
36736     68/push 0x11/imm32/alloc-id:fake:payload
36737     89/<- %edi 4/r32/esp
36738 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
36739     # primitives->name = "increment"
36740     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36741     (copy-array Heap "increment" %eax)
36742 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
36743     # primitives->subx-name = "ff 0/subop/increment"
36744     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36745     (copy-array Heap "ff 0/subop/increment" %eax)
36746 $test-emit-subx-stmt-select-primitive:initialize-primitive:
36747     # var primitives/ebx: (addr primitive)
36748     57/push-edi
36749     68/push 0x11/imm32/alloc-id:fake
36750     68/push 0/imm32/no-x32
36751     68/push 0/imm32/no-xm32
36752     68/push 0/imm32/no-disp32
36753     68/push 0/imm32/no-imm8
36754     68/push 0/imm32/no-imm32
36755     68/push 0/imm32/no-r32
36756     68/push 1/imm32/rm32-is-first-inout
36757     68/push 0/imm32/subx-name
36758     68/push 0/imm32/subx-name
36759     68/push 0/imm32/no-outputs
36760     68/push 0/imm32/no-outputs
36761     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36762     68/push 0x11/imm32/alloc-id:fake
36763     68/push 0/imm32/name
36764     68/push 0/imm32/name
36765     89/<- %ebx 4/r32/esp
36766 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
36767     # primitives->name = "increment"
36768     (copy-array Heap "increment" %ebx)  # Primitive-name
36769 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
36770     # primitives->subx-name = "ff 0/subop/increment"
36771     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36772     (copy-array Heap "ff 0/subop/increment" %eax)
36773     # convert
36774     c7 0/subop/copy *Curr-block-depth 0/imm32
36775     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36776     (flush _test-output-buffered-file)
36777 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36783     # check output
36784     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
36785     # . epilogue
36786     89/<- %esp 5/r32/ebp
36787     5d/pop-to-ebp
36788     c3/return
36789 
36790 test-emit-subx-stmt-select-primitive-2:
36791     # Select the right primitive between overloads.
36792     #   increment foo
36793     # =>
36794     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
36795     #
36796     # There's a variable on the var stack as follows:
36797     #   name: 'foo'
36798     #   type: int
36799     #   register: 'eax'
36800     #
36801     # There's two primitives, as follows:
36802     #   - name: 'increment'
36803     #     out: int/reg
36804     #     value: 'ff 0/subop/increment'
36805     #   - name: 'increment'
36806     #     inout: int/mem
36807     #     value: 'ff 0/subop/increment'
36808     #
36809     # . prologue
36810     55/push-ebp
36811     89/<- %ebp 4/r32/esp
36812     # setup
36813     (clear-stream _test-output-stream)
36814     (clear-stream $_test-output-buffered-file->buffer)
36815 $test-emit-subx-stmt-select-primitive-2:initialize-type:
36816     # var type/ecx: (payload type-tree) = int
36817     68/push 0/imm32/right:null
36818     68/push 0/imm32/right:null
36819     68/push 0/imm32/left:unused
36820     68/push 1/imm32/value:int
36821     68/push 1/imm32/is-atom?:true
36822     68/push 0x11/imm32/alloc-id:fake:payload
36823     89/<- %ecx 4/r32/esp
36824 $test-emit-subx-stmt-select-primitive-2:initialize-var:
36825     # var var-foo/ecx: (payload var)
36826     68/push 0/imm32/register
36827     68/push 0/imm32/register
36828     68/push 0/imm32/no-stack-offset
36829     68/push 1/imm32/block-depth
36830     51/push-ecx
36831     68/push 0x11/imm32/alloc-id:fake
36832     68/push 0/imm32/name
36833     68/push 0/imm32/name
36834     68/push 0x11/imm32/alloc-id:fake:payload
36835     89/<- %ecx 4/r32/esp
36836 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
36837     # var-foo->name = "foo"
36838     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
36839     (copy-array Heap "foo" %eax)
36840 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
36841     # var-foo->register = "eax"
36842     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
36843     (copy-array Heap "eax" %eax)
36844 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
36845     # var operand/ebx: (payload stmt-var)
36846     68/push 0/imm32/is-deref:false
36847     68/push 0/imm32/next
36848     68/push 0/imm32/next
36849     51/push-ecx/var-foo
36850     68/push 0x11/imm32/alloc-id:fake
36851     68/push 0x11/imm32/alloc-id:fake:payload
36852     89/<- %ebx 4/r32/esp
36853 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
36854     # var stmt/esi: (addr statement)
36855     68/push 0/imm32/no-outputs
36856     68/push 0/imm32/no-outputs
36857     53/push-ebx/inouts
36858     68/push 0x11/imm32/alloc-id:fake
36859     68/push 0/imm32/operation
36860     68/push 0/imm32/operation
36861     68/push 1/imm32
36862     89/<- %esi 4/r32/esp
36863 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
36864     # stmt->operation = "increment"
36865     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
36866     (copy-array Heap "increment" %eax)
36867 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
36868     # var formal-var/ebx: (payload var)
36869     68/push 0/imm32/register
36870     68/push 0/imm32/register
36871     68/push 0/imm32/no-stack-offset
36872     68/push 1/imm32/block-depth
36873     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
36874     68/push 0x11/imm32/alloc-id:fake
36875     68/push 0/imm32/name
36876     68/push 0/imm32/name
36877     68/push 0x11/imm32/alloc-id:fake:payload
36878     89/<- %ebx 4/r32/esp
36879 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
36880     # formal-var->name = "dummy"
36881     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
36882     (copy-array Heap "dummy" %eax)
36883 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
36884     # formal-var->register = "*"
36885     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
36886     (copy-array Heap "*" %eax)  # Any-register
36887 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
36888     # var formal-outputs/ebx: (payload list stmt-var)
36889     68/push 0/imm32/next
36890     68/push 0/imm32/next
36891     53/push-ebx/formal-var
36892     68/push 0x11/imm32/alloc-id:fake
36893     68/push 0x11/imm32/alloc-id:fake:payload
36894     89/<- %ebx 4/r32/esp
36895 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
36896     # var primitive2/edi: (payload primitive)
36897     68/push 0/imm32/next
36898     68/push 0/imm32/next
36899     68/push 0/imm32/no-x32
36900     68/push 0/imm32/no-xm32
36901     68/push 0/imm32/no-disp32
36902     68/push 0/imm32/no-imm8
36903     68/push 0/imm32/no-imm32
36904     68/push 0/imm32/no-r32
36905     68/push 3/imm32/rm32-is-first-output
36906     68/push 0/imm32/subx-name
36907     68/push 0/imm32/subx-name
36908     53/push-ebx/outputs
36909     68/push 0x11/imm32/alloc-id:fake
36910     68/push 0/imm32/no-inouts
36911     68/push 0/imm32/no-inouts
36912     68/push 0/imm32/name
36913     68/push 0/imm32/name
36914     68/push 0x11/imm32/alloc-id:fake:payload
36915     89/<- %edi 4/r32/esp
36916 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
36917     # primitives->name = "increment"
36918     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
36919     (copy-array Heap "increment" %eax)
36920 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
36921     # primitives->subx-name = "ff 0/subop/increment"
36922     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
36923     (copy-array Heap "ff 0/subop/increment" %eax)
36924 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
36925     # var primitives/ebx: (addr primitive)
36926     57/push-edi
36927     68/push 0x11/imm32/alloc-id:fake
36928     68/push 0/imm32/no-x32
36929     68/push 0/imm32/no-xm32
36930     68/push 0/imm32/no-disp32
36931     68/push 0/imm32/no-imm8
36932     68/push 0/imm32/no-imm32
36933     68/push 0/imm32/no-r32
36934     68/push 1/imm32/rm32-is-first-inout
36935     68/push 0/imm32/subx-name
36936     68/push 0/imm32/subx-name
36937     68/push 0/imm32/no-outputs
36938     68/push 0/imm32/no-outputs
36939     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
36940     68/push 0x11/imm32/alloc-id:fake
36941     68/push 0/imm32/name
36942     68/push 0/imm32/name
36943     89/<- %ebx 4/r32/esp
36944 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
36945     # primitives->name = "increment"
36946     (copy-array Heap "increment" %ebx)  # Primitive-name
36947 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
36948     # primitives->subx-name = "ff 0/subop/increment"
36949     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
36950     (copy-array Heap "ff 0/subop/increment" %eax)
36951     # convert
36952     c7 0/subop/copy *Curr-block-depth 0/imm32
36953     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
36954     (flush _test-output-buffered-file)
36955 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
36961     # check output
36962     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
36963     # . epilogue
36964     89/<- %esp 5/r32/ebp
36965     5d/pop-to-ebp
36966     c3/return
36967 
36968 test-increment-register:
36969     # Select the right register between overloads.
36970     #   foo <- increment
36971     # =>
36972     #   50/increment-eax
36973     #
36974     # There's a variable on the var stack as follows:
36975     #   name: 'foo'
36976     #   type: int
36977     #   register: 'eax'
36978     #
36979     # Primitives are the global definitions.
36980     #
36981     # . prologue
36982     55/push-ebp
36983     89/<- %ebp 4/r32/esp
36984     # setup
36985     (clear-stream _test-output-stream)
36986     (clear-stream $_test-output-buffered-file->buffer)
36987 $test-increment-register:initialize-type:
36988     # var type/ecx: (payload type-tree) = int
36989     68/push 0/imm32/right:null
36990     68/push 0/imm32/right:null
36991     68/push 0/imm32/left:unused
36992     68/push 1/imm32/value:int
36993     68/push 1/imm32/is-atom?:true
36994     68/push 0x11/imm32/alloc-id:fake:payload
36995     89/<- %ecx 4/r32/esp
36996 $test-increment-register:initialize-var:
36997     # var var-foo/ecx: (payload var)
36998     68/push 0/imm32/register
36999     68/push 0/imm32/register
37000     68/push 0/imm32/no-stack-offset
37001     68/push 1/imm32/block-depth
37002     51/push-ecx
37003     68/push 0x11/imm32/alloc-id:fake
37004     68/push 0/imm32/name
37005     68/push 0/imm32/name
37006     68/push 0x11/imm32/alloc-id:fake:payload
37007     89/<- %ecx 4/r32/esp
37008 $test-increment-register:initialize-var-name:
37009     # var-foo->name = "foo"
37010     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37011     (copy-array Heap "foo" %eax)
37012 $test-increment-register:initialize-var-register:
37013     # var-foo->register = "eax"
37014     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37015     (copy-array Heap "eax" %eax)
37016 $test-increment-register:initialize-stmt-var:
37017     # var operand/ebx: (payload stmt-var)
37018     68/push 0/imm32/is-deref:false
37019     68/push 0/imm32/next
37020     68/push 0/imm32/next
37021     51/push-ecx/var-foo
37022     68/push 0x11/imm32/alloc-id:fake
37023     68/push 0x11/imm32/alloc-id:fake:payload
37024     89/<- %ebx 4/r32/esp
37025 $test-increment-register:initialize-stmt:
37026     # var stmt/esi: (addr statement)
37027     53/push-ebx/outputs
37028     68/push 0x11/imm32/alloc-id:fake
37029     68/push 0/imm32/no-inouts
37030     68/push 0/imm32/no-inouts
37031     68/push 0/imm32/operation
37032     68/push 0/imm32/operation
37033     68/push 1/imm32
37034     89/<- %esi 4/r32/esp
37035 $test-increment-register:initialize-stmt-operation:
37036     # stmt->operation = "increment"
37037     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37038     (copy-array Heap "increment" %eax)
37039     # convert
37040     c7 0/subop/copy *Curr-block-depth 0/imm32
37041     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37042     (flush _test-output-buffered-file)
37043 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37049     # check output
37050     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
37051     # . epilogue
37052     89/<- %esp 5/r32/ebp
37053     5d/pop-to-ebp
37054     c3/return
37055 
37056 test-add-reg-to-reg:
37057     #   var1/reg <- add var2/reg
37058     # =>
37059     #   01/add-to %var1 var2
37060     #
37061     # . prologue
37062     55/push-ebp
37063     89/<- %ebp 4/r32/esp
37064     # setup
37065     (clear-stream _test-output-stream)
37066     (clear-stream $_test-output-buffered-file->buffer)
37067 $test-add-reg-to-reg:initialize-type:
37068     # var type/ecx: (payload type-tree) = int
37069     68/push 0/imm32/right:null
37070     68/push 0/imm32/right:null
37071     68/push 0/imm32/left:unused
37072     68/push 1/imm32/value:int
37073     68/push 1/imm32/is-atom?:true
37074     68/push 0x11/imm32/alloc-id:fake:payload
37075     89/<- %ecx 4/r32/esp
37076 $test-add-reg-to-reg:initialize-var1:
37077     # var var1/ecx: (payload var)
37078     68/push 0/imm32/register
37079     68/push 0/imm32/register
37080     68/push 0/imm32/no-stack-offset
37081     68/push 1/imm32/block-depth
37082     51/push-ecx
37083     68/push 0x11/imm32/alloc-id:fake
37084     68/push 0/imm32/name
37085     68/push 0/imm32/name
37086     68/push 0x11/imm32/alloc-id:fake:payload
37087     89/<- %ecx 4/r32/esp
37088 $test-add-reg-to-reg:initialize-var1-name:
37089     # var1->name = "var1"
37090     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37091     (copy-array Heap "var1" %eax)
37092 $test-add-reg-to-reg:initialize-var1-register:
37093     # var1->register = "eax"
37094     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37095     (copy-array Heap "eax" %eax)
37096 $test-add-reg-to-reg:initialize-var2:
37097     # var var2/edx: (payload var)
37098     68/push 0/imm32/register
37099     68/push 0/imm32/register
37100     68/push 0/imm32/no-stack-offset
37101     68/push 1/imm32/block-depth
37102     ff 6/subop/push *(ecx+0x10)
37103     68/push 0x11/imm32/alloc-id:fake
37104     68/push 0/imm32/name
37105     68/push 0/imm32/name
37106     68/push 0x11/imm32/alloc-id:fake:payload
37107     89/<- %edx 4/r32/esp
37108 $test-add-reg-to-reg:initialize-var2-name:
37109     # var2->name = "var2"
37110     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37111     (copy-array Heap "var2" %eax)
37112 $test-add-reg-to-reg:initialize-var2-register:
37113     # var2->register = "ecx"
37114     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37115     (copy-array Heap "ecx" %eax)
37116 $test-add-reg-to-reg:initialize-inouts:
37117     # var inouts/esi: (payload stmt-var) = [var2]
37118     68/push 0/imm32/is-deref:false
37119     68/push 0/imm32/next
37120     68/push 0/imm32/next
37121     52/push-edx/var2
37122     68/push 0x11/imm32/alloc-id:fake
37123     68/push 0x11/imm32/alloc-id:fake:payload
37124     89/<- %esi 4/r32/esp
37125 $test-add-reg-to-reg:initialize-outputs:
37126     # var outputs/edi: (payload stmt-var) = [var1]
37127     68/push 0/imm32/is-deref:false
37128     68/push 0/imm32/next
37129     68/push 0/imm32/next
37130     51/push-ecx/var1
37131     68/push 0x11/imm32/alloc-id:fake
37132     68/push 0x11/imm32/alloc-id:fake:payload
37133     89/<- %edi 4/r32/esp
37134 $test-add-reg-to-reg:initialize-stmt:
37135     # var stmt/esi: (addr statement)
37136     68/push 0/imm32/next
37137     68/push 0/imm32/next
37138     57/push-edi/outputs
37139     68/push 0x11/imm32/alloc-id:fake
37140     56/push-esi/inouts
37141     68/push 0x11/imm32/alloc-id:fake
37142     68/push 0/imm32/operation
37143     68/push 0/imm32/operation
37144     68/push 1/imm32/tag:stmt1
37145     89/<- %esi 4/r32/esp
37146 $test-add-reg-to-reg:initialize-stmt-operation:
37147     # stmt->operation = "add"
37148     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37149     (copy-array Heap "add" %eax)
37150     # convert
37151     c7 0/subop/copy *Curr-block-depth 0/imm32
37152     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37153     (flush _test-output-buffered-file)
37154 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37160     # check output
37161     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
37162     # . epilogue
37163     89/<- %esp 5/r32/ebp
37164     5d/pop-to-ebp
37165     c3/return
37166 
37167 test-add-reg-to-mem:
37168     #   add-to var1 var2/reg
37169     # =>
37170     #   01/add-to *(ebp+__) var2
37171     #
37172     # . prologue
37173     55/push-ebp
37174     89/<- %ebp 4/r32/esp
37175     # setup
37176     (clear-stream _test-output-stream)
37177     (clear-stream $_test-output-buffered-file->buffer)
37178 $test-add-reg-to-mem:initialize-type:
37179     # var type/ecx: (payload type-tree) = int
37180     68/push 0/imm32/right:null
37181     68/push 0/imm32/right:null
37182     68/push 0/imm32/left:unused
37183     68/push 1/imm32/value:int
37184     68/push 1/imm32/is-atom?:true
37185     68/push 0x11/imm32/alloc-id:fake:payload
37186     89/<- %ecx 4/r32/esp
37187 $test-add-reg-to-mem:initialize-var1:
37188     # var var1/ecx: (payload var)
37189     68/push 0/imm32/register
37190     68/push 0/imm32/register
37191     68/push 8/imm32/stack-offset
37192     68/push 1/imm32/block-depth
37193     51/push-ecx
37194     68/push 0x11/imm32/alloc-id:fake
37195     68/push 0/imm32/name
37196     68/push 0/imm32/name
37197     68/push 0x11/imm32/alloc-id:fake:payload
37198     89/<- %ecx 4/r32/esp
37199 $test-add-reg-to-mem:initialize-var1-name:
37200     # var1->name = "var1"
37201     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37202     (copy-array Heap "var1" %eax)
37203 $test-add-reg-to-mem:initialize-var2:
37204     # var var2/edx: (payload var)
37205     68/push 0/imm32/register
37206     68/push 0/imm32/register
37207     68/push 0/imm32/no-stack-offset
37208     68/push 1/imm32/block-depth
37209     ff 6/subop/push *(ecx+0x10)
37210     68/push 0x11/imm32/alloc-id:fake
37211     68/push 0/imm32/name
37212     68/push 0/imm32/name
37213     68/push 0x11/imm32/alloc-id:fake:payload
37214     89/<- %edx 4/r32/esp
37215 $test-add-reg-to-mem:initialize-var2-name:
37216     # var2->name = "var2"
37217     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37218     (copy-array Heap "var2" %eax)
37219 $test-add-reg-to-mem:initialize-var2-register:
37220     # var2->register = "ecx"
37221     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
37222     (copy-array Heap "ecx" %eax)
37223 $test-add-reg-to-mem:initialize-inouts:
37224     # var inouts/esi: (payload stmt-var) = [var2]
37225     68/push 0/imm32/is-deref:false
37226     68/push 0/imm32/next
37227     68/push 0/imm32/next
37228     52/push-edx/var2
37229     68/push 0x11/imm32/alloc-id:fake
37230     68/push 0x11/imm32/alloc-id:fake:payload
37231     89/<- %esi 4/r32/esp
37232     # inouts = [var1, var2]
37233     68/push 0/imm32/is-deref:false
37234     56/push-esi/next
37235     68/push 0x11/imm32/alloc-id:fake
37236     51/push-ecx/var1
37237     68/push 0x11/imm32/alloc-id:fake
37238     68/push 0x11/imm32/alloc-id:fake:payload
37239     89/<- %esi 4/r32/esp
37240 $test-add-reg-to-mem:initialize-stmt:
37241     # var stmt/esi: (addr statement)
37242     68/push 0/imm32/next
37243     68/push 0/imm32/next
37244     68/push 0/imm32/outputs
37245     68/push 0/imm32/outputs
37246     56/push-esi/inouts
37247     68/push 0x11/imm32/alloc-id:fake
37248     68/push 0/imm32/operation
37249     68/push 0/imm32/operation
37250     68/push 1/imm32/tag:stmt1
37251     89/<- %esi 4/r32/esp
37252 $test-add-reg-to-mem:initialize-stmt-operation:
37253     # stmt->operation = "add-to"
37254     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37255     (copy-array Heap "add-to" %eax)
37256     # convert
37257     c7 0/subop/copy *Curr-block-depth 0/imm32
37258     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37259     (flush _test-output-buffered-file)
37260 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37266     # check output
37267     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
37268     # . epilogue
37269     89/<- %esp 5/r32/ebp
37270     5d/pop-to-ebp
37271     c3/return
37272 
37273 test-add-mem-to-reg:
37274     #   var1/reg <- add var2
37275     # =>
37276     #   03/add *(ebp+__) var1
37277     #
37278     # . prologue
37279     55/push-ebp
37280     89/<- %ebp 4/r32/esp
37281     # setup
37282     (clear-stream _test-output-stream)
37283     (clear-stream $_test-output-buffered-file->buffer)
37284 $test-add-mem-to-reg:initialize-type:
37285     # var type/ecx: (payload type-tree) = int
37286     68/push 0/imm32/right:null
37287     68/push 0/imm32/right:null
37288     68/push 0/imm32/left:unused
37289     68/push 1/imm32/value:int
37290     68/push 1/imm32/is-atom?:true
37291     68/push 0x11/imm32/alloc-id:fake:payload
37292     89/<- %ecx 4/r32/esp
37293 $test-add-mem-to-reg:initialize-var:
37294     # var var1/ecx: (payload var)
37295     68/push 0/imm32/register
37296     68/push 0/imm32/register
37297     68/push 0/imm32/no-stack-offset
37298     68/push 1/imm32/block-depth
37299     51/push-ecx
37300     68/push 0x11/imm32/alloc-id:fake
37301     68/push 0/imm32/name
37302     68/push 0/imm32/name
37303     68/push 0x11/imm32/alloc-id:fake:payload
37304     89/<- %ecx 4/r32/esp
37305 $test-add-mem-to-reg:initialize-var-name:
37306     # var1->name = "foo"
37307     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37308     (copy-array Heap "var1" %eax)
37309 $test-add-mem-to-reg:initialize-var-register:
37310     # var1->register = "eax"
37311     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37312     (copy-array Heap "eax" %eax)
37313 $test-add-mem-to-reg:initialize-var2:
37314     # var var2/edx: (payload var)
37315     68/push 0/imm32/register
37316     68/push 0/imm32/register
37317     68/push 8/imm32/stack-offset
37318     68/push 1/imm32/block-depth
37319     ff 6/subop/push *(ecx+0x10)
37320     68/push 0x11/imm32/alloc-id:fake
37321     68/push 0/imm32/name
37322     68/push 0/imm32/name
37323     68/push 0x11/imm32/alloc-id:fake:payload
37324     89/<- %edx 4/r32/esp
37325 $test-add-mem-to-reg:initialize-var2-name:
37326     # var2->name = "var2"
37327     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37328     (copy-array Heap "var2" %eax)
37329 $test-add-mem-to-reg:initialize-inouts:
37330     # var inouts/esi: (payload stmt-var) = [var2]
37331     68/push 0/imm32/is-deref:false
37332     68/push 0/imm32/next
37333     68/push 0/imm32/next
37334     52/push-edx/var2
37335     68/push 0x11/imm32/alloc-id:fake
37336     68/push 0x11/imm32/alloc-id:fake:payload
37337     89/<- %esi 4/r32/esp
37338 $test-add-mem-to-reg:initialize-outputs:
37339     # var outputs/edi: (payload stmt-var) = [var1]
37340     68/push 0/imm32/is-deref:false
37341     68/push 0/imm32/next
37342     68/push 0/imm32/next
37343     51/push-ecx/var1
37344     68/push 0x11/imm32/alloc-id:fake
37345     68/push 0x11/imm32/alloc-id:fake:payload
37346     89/<- %edi 4/r32/esp
37347 $test-add-mem-to-reg:initialize-stmt:
37348     # var stmt/esi: (addr statement)
37349     68/push 0/imm32/next
37350     68/push 0/imm32/next
37351     57/push-edi/outputs
37352     68/push 0x11/imm32/alloc-id:fake
37353     56/push-esi/inouts
37354     68/push 0x11/imm32/alloc-id:fake
37355     68/push 0/imm32/operation
37356     68/push 0/imm32/operation
37357     68/push 1/imm32/tag:stmt1
37358     89/<- %esi 4/r32/esp
37359 $test-add-mem-to-reg:initialize-stmt-operation:
37360     # stmt->operation = "add"
37361     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37362     (copy-array Heap "add" %eax)
37363     # convert
37364     c7 0/subop/copy *Curr-block-depth 0/imm32
37365     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37366     (flush _test-output-buffered-file)
37367 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37373     # check output
37374     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
37375     # . epilogue
37376     89/<- %esp 5/r32/ebp
37377     5d/pop-to-ebp
37378     c3/return
37379 
37380 test-add-literal-to-eax:
37381     #   var1/eax <- add 0x34
37382     # =>
37383     #   05/add-to-eax 0x34/imm32
37384     #
37385     # . prologue
37386     55/push-ebp
37387     89/<- %ebp 4/r32/esp
37388     # setup
37389     (clear-stream _test-output-stream)
37390     (clear-stream $_test-output-buffered-file->buffer)
37391 $test-add-literal-to-eax:initialize-var-type:
37392     # var type/ecx: (payload type-tree) = int
37393     68/push 0/imm32/right:null
37394     68/push 0/imm32/right:null
37395     68/push 0/imm32/left:unused
37396     68/push 1/imm32/value:int
37397     68/push 1/imm32/is-atom?:true
37398     68/push 0x11/imm32/alloc-id:fake:payload
37399     89/<- %ecx 4/r32/esp
37400 $test-add-literal-to-eax:initialize-var:
37401     # var v/ecx: (payload var)
37402     68/push 0/imm32/register
37403     68/push 0/imm32/register
37404     68/push 0/imm32/no-stack-offset
37405     68/push 1/imm32/block-depth
37406     51/push-ecx
37407     68/push 0x11/imm32/alloc-id:fake
37408     68/push 0/imm32/name
37409     68/push 0/imm32/name
37410     68/push 0x11/imm32/alloc-id:fake:payload
37411     89/<- %ecx 4/r32/esp
37412 $test-add-literal-to-eax:initialize-var-name:
37413     # v->name = "v"
37414     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37415     (copy-array Heap "v" %eax)
37416 $test-add-literal-to-eax:initialize-var-register:
37417     # v->register = "eax"
37418     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37419     (copy-array Heap "eax" %eax)
37420 $test-add-literal-to-eax:initialize-literal-type:
37421     # var type/edx: (payload type-tree) = literal
37422     68/push 0/imm32/right:null
37423     68/push 0/imm32/right:null
37424     68/push 0/imm32/left:unused
37425     68/push 0/imm32/value:literal
37426     68/push 1/imm32/is-atom?:true
37427     68/push 0x11/imm32/alloc-id:fake:payload
37428     89/<- %edx 4/r32/esp
37429 $test-add-literal-to-eax:initialize-literal:
37430     # var l/edx: (payload var)
37431     68/push 0/imm32/register
37432     68/push 0/imm32/register
37433     68/push 0/imm32/no-stack-offset
37434     68/push 1/imm32/block-depth
37435     52/push-edx
37436     68/push 0x11/imm32/alloc-id:fake
37437     68/push 0/imm32/name
37438     68/push 0/imm32/name
37439     68/push 0x11/imm32/alloc-id:fake:payload
37440     89/<- %edx 4/r32/esp
37441 $test-add-literal-to-eax:initialize-literal-value:
37442     # l->name = "0x34"
37443     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37444     (copy-array Heap "0x34" %eax)
37445 $test-add-literal-to-eax:initialize-inouts:
37446     # var inouts/esi: (payload stmt-var) = [l]
37447     68/push 0/imm32/is-deref:false
37448     68/push 0/imm32/next
37449     68/push 0/imm32/next
37450     52/push-edx/l
37451     68/push 0x11/imm32/alloc-id:fake
37452     68/push 0x11/imm32/alloc-id:fake:payload
37453     89/<- %esi 4/r32/esp
37454 $test-add-literal-to-eax:initialize-outputs:
37455     # var outputs/edi: (payload stmt-var) = [v]
37456     68/push 0/imm32/is-deref:false
37457     68/push 0/imm32/next
37458     68/push 0/imm32/next
37459     51/push-ecx/v
37460     68/push 0x11/imm32/alloc-id:fake
37461     68/push 0x11/imm32/alloc-id:fake:payload
37462     89/<- %edi 4/r32/esp
37463 $test-add-literal-to-eax:initialize-stmt:
37464     # var stmt/esi: (addr statement)
37465     68/push 0/imm32/next
37466     68/push 0/imm32/next
37467     57/push-edi/outputs
37468     68/push 0x11/imm32/alloc-id:fake
37469     56/push-esi/inouts
37470     68/push 0x11/imm32/alloc-id:fake
37471     68/push 0/imm32/operation
37472     68/push 0/imm32/operation
37473     68/push 1/imm32/tag:stmt1
37474     89/<- %esi 4/r32/esp
37475 $test-add-literal-to-eax:initialize-stmt-operation:
37476     # stmt->operation = "add"
37477     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37478     (copy-array Heap "add" %eax)
37479     # convert
37480     c7 0/subop/copy *Curr-block-depth 0/imm32
37481     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37482     (flush _test-output-buffered-file)
37483 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37489     # check output
37490     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
37491     # . epilogue
37492     89/<- %esp 5/r32/ebp
37493     5d/pop-to-ebp
37494     c3/return
37495 
37496 test-add-literal-to-reg:
37497     #   var1/ecx <- add 0x34
37498     # =>
37499     #   81 0/subop/add %ecx 0x34/imm32
37500     #
37501     # . prologue
37502     55/push-ebp
37503     89/<- %ebp 4/r32/esp
37504     # setup
37505     (clear-stream _test-output-stream)
37506     (clear-stream $_test-output-buffered-file->buffer)
37507 $test-add-literal-to-reg:initialize-var-type:
37508     # var type/ecx: (payload type-tree) = int
37509     68/push 0/imm32/right:null
37510     68/push 0/imm32/right:null
37511     68/push 0/imm32/left:unused
37512     68/push 1/imm32/value:int
37513     68/push 1/imm32/is-atom?:true
37514     68/push 0x11/imm32/alloc-id:fake:payload
37515     89/<- %ecx 4/r32/esp
37516 $test-add-literal-to-reg:initialize-var:
37517     # var v/ecx: (payload var)
37518     68/push 0/imm32/register
37519     68/push 0/imm32/register
37520     68/push 0/imm32/no-stack-offset
37521     68/push 1/imm32/block-depth
37522     51/push-ecx
37523     68/push 0x11/imm32/alloc-id:fake
37524     68/push 0/imm32/name
37525     68/push 0/imm32/name
37526     68/push 0x11/imm32/alloc-id:fake:payload
37527     89/<- %ecx 4/r32/esp
37528 $test-add-literal-to-reg:initialize-var-name:
37529     # v->name = "v"
37530     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37531     (copy-array Heap "v" %eax)
37532 $test-add-literal-to-reg:initialize-var-register:
37533     # v->register = "ecx"
37534     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37535     (copy-array Heap "ecx" %eax)
37536 $test-add-literal-to-reg:initialize-literal-type:
37537     # var type/edx: (payload type-tree) = literal
37538     68/push 0/imm32/right:null
37539     68/push 0/imm32/right:null
37540     68/push 0/imm32/left:unused
37541     68/push 0/imm32/value:literal
37542     68/push 1/imm32/is-atom?:true
37543     68/push 0x11/imm32/alloc-id:fake:payload
37544     89/<- %edx 4/r32/esp
37545 $test-add-literal-to-reg:initialize-literal:
37546     # var l/edx: (payload var)
37547     68/push 0/imm32/register
37548     68/push 0/imm32/register
37549     68/push 0/imm32/no-stack-offset
37550     68/push 1/imm32/block-depth
37551     52/push-edx
37552     68/push 0x11/imm32/alloc-id:fake
37553     68/push 0/imm32/name
37554     68/push 0/imm32/name
37555     68/push 0x11/imm32/alloc-id:fake:payload
37556     89/<- %edx 4/r32/esp
37557 $test-add-literal-to-reg:initialize-literal-value:
37558     # l->name = "0x34"
37559     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37560     (copy-array Heap "0x34" %eax)
37561 $test-add-literal-to-reg:initialize-inouts:
37562     # var inouts/esi: (payload stmt-var) = [l]
37563     68/push 0/imm32/is-deref:false
37564     68/push 0/imm32/next
37565     68/push 0/imm32/next
37566     52/push-edx/l
37567     68/push 0x11/imm32/alloc-id:fake
37568     68/push 0x11/imm32/alloc-id:fake:payload
37569     89/<- %esi 4/r32/esp
37570 $test-add-literal-to-reg:initialize-outputs:
37571     # var outputs/edi: (payload stmt-var) = [v]
37572     68/push 0/imm32/is-deref:false
37573     68/push 0/imm32/next
37574     68/push 0/imm32/next
37575     51/push-ecx/v
37576     68/push 0x11/imm32/alloc-id:fake
37577     68/push 0x11/imm32/alloc-id:fake:payload
37578     89/<- %edi 4/r32/esp
37579 $test-add-literal-to-reg:initialize-stmt:
37580     # var stmt/esi: (addr statement)
37581     68/push 0/imm32/next
37582     68/push 0/imm32/next
37583     57/push-edi/outputs
37584     68/push 0x11/imm32/alloc-id:fake
37585     56/push-esi/inouts
37586     68/push 0x11/imm32/alloc-id:fake
37587     68/push 0/imm32/operation
37588     68/push 0/imm32/operation
37589     68/push 1/imm32/tag:stmt1
37590     89/<- %esi 4/r32/esp
37591 $test-add-literal-to-reg:initialize-stmt-operation:
37592     # stmt->operation = "add"
37593     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37594     (copy-array Heap "add" %eax)
37595     # convert
37596     c7 0/subop/copy *Curr-block-depth 0/imm32
37597     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37598     (flush _test-output-buffered-file)
37599 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37605     # check output
37606     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
37607     # . epilogue
37608     89/<- %esp 5/r32/ebp
37609     5d/pop-to-ebp
37610     c3/return
37611 
37612 test-add-literal-to-mem:
37613     #   add-to var1, 0x34
37614     # =>
37615     #   81 0/subop/add %eax 0x34/imm32
37616     #
37617     # . prologue
37618     55/push-ebp
37619     89/<- %ebp 4/r32/esp
37620     # setup
37621     (clear-stream _test-output-stream)
37622     (clear-stream $_test-output-buffered-file->buffer)
37623 $test-add-literal-to-mem:initialize-type:
37624     # var type/ecx: (payload type-tree) = int
37625     68/push 0/imm32/right:null
37626     68/push 0/imm32/right:null
37627     68/push 0/imm32/left:unused
37628     68/push 1/imm32/value:int
37629     68/push 1/imm32/is-atom?:true
37630     68/push 0x11/imm32/alloc-id:fake:payload
37631     89/<- %ecx 4/r32/esp
37632 $test-add-literal-to-mem:initialize-var1:
37633     # var var1/ecx: (payload var)
37634     68/push 0/imm32/register
37635     68/push 0/imm32/register
37636     68/push 8/imm32/stack-offset
37637     68/push 1/imm32/block-depth
37638     51/push-ecx
37639     68/push 0x11/imm32/alloc-id:fake
37640     68/push 0/imm32/name
37641     68/push 0/imm32/name
37642     68/push 0x11/imm32/alloc-id:fake:payload
37643     89/<- %ecx 4/r32/esp
37644 $test-add-literal-to-mem:initialize-var1-name:
37645     # var1->name = "var1"
37646     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37647     (copy-array Heap "var1" %eax)
37648 $test-add-literal-to-mem:initialize-literal-type:
37649     # var type/edx: (payload type-tree) = literal
37650     68/push 0/imm32/right:null
37651     68/push 0/imm32/right:null
37652     68/push 0/imm32/left:unused
37653     68/push 0/imm32/value:literal
37654     68/push 1/imm32/is-atom?:true
37655     68/push 0x11/imm32/alloc-id:fake:payload
37656     89/<- %edx 4/r32/esp
37657 $test-add-literal-to-mem:initialize-literal:
37658     # var l/edx: (payload var)
37659     68/push 0/imm32/register
37660     68/push 0/imm32/register
37661     68/push 0/imm32/no-stack-offset
37662     68/push 1/imm32/block-depth
37663     52/push-edx
37664     68/push 0x11/imm32/alloc-id:fake
37665     68/push 0/imm32/name
37666     68/push 0/imm32/name
37667     68/push 0x11/imm32/alloc-id:fake:payload
37668     89/<- %edx 4/r32/esp
37669 $test-add-literal-to-mem:initialize-literal-value:
37670     # l->name = "0x34"
37671     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37672     (copy-array Heap "0x34" %eax)
37673 $test-add-literal-to-mem:initialize-inouts:
37674     # var inouts/esi: (payload stmt-var) = [l]
37675     68/push 0/imm32/is-deref:false
37676     68/push 0/imm32/next
37677     68/push 0/imm32/next
37678     52/push-edx/l
37679     68/push 0x11/imm32/alloc-id:fake
37680     68/push 0x11/imm32/alloc-id:fake:payload
37681     89/<- %esi 4/r32/esp
37682     # var inouts = (handle stmt-var) = [var1, var2]
37683     68/push 0/imm32/is-deref:false
37684     56/push-esi/next
37685     68/push 0x11/imm32/alloc-id:fake
37686     51/push-ecx/var1
37687     68/push 0x11/imm32/alloc-id:fake
37688     68/push 0x11/imm32/alloc-id:fake:payload
37689     89/<- %esi 4/r32/esp
37690 $test-add-literal-to-mem:initialize-stmt:
37691     # var stmt/esi: (addr statement)
37692     68/push 0/imm32/next
37693     68/push 0/imm32/next
37694     68/push 0/imm32/outputs
37695     68/push 0/imm32/outputs
37696     56/push-esi/inouts
37697     68/push 0x11/imm32/alloc-id:fake
37698     68/push 0/imm32/operation
37699     68/push 0/imm32/operation
37700     68/push 1/imm32/tag:stmt1
37701     89/<- %esi 4/r32/esp
37702 $test-add-literal-to-mem:initialize-stmt-operation:
37703     # stmt->operation = "add-to"
37704     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37705     (copy-array Heap "add-to" %eax)
37706     # convert
37707     c7 0/subop/copy *Curr-block-depth 0/imm32
37708     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37709     (flush _test-output-buffered-file)
37710 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37716     # check output
37717     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
37718     # . epilogue
37719     89/<- %esp 5/r32/ebp
37720     5d/pop-to-ebp
37721     c3/return
37722 
37723 test-shift-reg-by-literal:
37724     #   var1/ecx <- shift-left 2
37725     # =>
37726     #   c1/shift 4/subop/left %ecx 2/imm8
37727     #
37728     # . prologue
37729     55/push-ebp
37730     89/<- %ebp 4/r32/esp
37731     # setup
37732     (clear-stream _test-output-stream)
37733     (clear-stream $_test-output-buffered-file->buffer)
37734 $test-shift-reg-by-literal:initialize-var-type:
37735     # var type/ecx: (payload type-tree) = int
37736     68/push 0/imm32/right:null
37737     68/push 0/imm32/right:null
37738     68/push 0/imm32/left:unused
37739     68/push 1/imm32/value:int
37740     68/push 1/imm32/is-atom?:true
37741     68/push 0x11/imm32/alloc-id:fake:payload
37742     89/<- %ecx 4/r32/esp
37743 $test-shift-reg-by-literal:initialize-var:
37744     # var v/ecx: (payload var)
37745     68/push 0/imm32/register
37746     68/push 0/imm32/register
37747     68/push 0/imm32/no-stack-offset
37748     68/push 1/imm32/block-depth
37749     51/push-ecx
37750     68/push 0x11/imm32/alloc-id:fake
37751     68/push 0/imm32/name
37752     68/push 0/imm32/name
37753     68/push 0x11/imm32/alloc-id:fake:payload
37754     89/<- %ecx 4/r32/esp
37755 $test-shift-reg-by-literal:initialize-var-name:
37756     # v->name = "v"
37757     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37758     (copy-array Heap "v" %eax)
37759 $test-shift-reg-by-literal:initialize-var-register:
37760     # v->register = "ecx"
37761     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37762     (copy-array Heap "ecx" %eax)
37763 $test-shift-reg-by-literal:initialize-literal-type:
37764     # var type/edx: (payload type-tree) = literal
37765     68/push 0/imm32/right:null
37766     68/push 0/imm32/right:null
37767     68/push 0/imm32/left:unused
37768     68/push 0/imm32/value:literal
37769     68/push 1/imm32/is-atom?:true
37770     68/push 0x11/imm32/alloc-id:fake:payload
37771     89/<- %edx 4/r32/esp
37772 $test-shift-reg-by-literal:initialize-literal:
37773     # var l/edx: (payload var)
37774     68/push 0/imm32/register
37775     68/push 0/imm32/register
37776     68/push 0/imm32/no-stack-offset
37777     68/push 1/imm32/block-depth
37778     52/push-edx
37779     68/push 0x11/imm32/alloc-id:fake
37780     68/push 0/imm32/name
37781     68/push 0/imm32/name
37782     68/push 0x11/imm32/alloc-id:fake:payload
37783     89/<- %edx 4/r32/esp
37784 $test-shift-reg-by-literal:initialize-literal-value:
37785     # l->name = "2"
37786     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37787     (copy-array Heap "2" %eax)
37788 $test-shift-reg-by-literal:initialize-inouts:
37789     # var inouts/esi: (payload stmt-var) = [l]
37790     68/push 0/imm32/is-deref:false
37791     68/push 0/imm32/next
37792     68/push 0/imm32/next
37793     52/push-edx/l
37794     68/push 0x11/imm32/alloc-id:fake
37795     68/push 0x11/imm32/alloc-id:fake:payload
37796     89/<- %esi 4/r32/esp
37797 $test-shift-reg-by-literal:initialize-outputs:
37798     # var outputs/edi: (payload stmt-var) = [v]
37799     68/push 0/imm32/is-deref:false
37800     68/push 0/imm32/next
37801     68/push 0/imm32/next
37802     51/push-ecx/v
37803     68/push 0x11/imm32/alloc-id:fake
37804     68/push 0x11/imm32/alloc-id:fake:payload
37805     89/<- %edi 4/r32/esp
37806 $test-shift-reg-by-literal:initialize-stmt:
37807     # var stmt/esi: (addr statement)
37808     68/push 0/imm32/next
37809     68/push 0/imm32/next
37810     57/push-edi/outputs
37811     68/push 0x11/imm32/alloc-id:fake
37812     56/push-esi/inouts
37813     68/push 0x11/imm32/alloc-id:fake
37814     68/push 0/imm32/operation
37815     68/push 0/imm32/operation
37816     68/push 1/imm32/tag:stmt1
37817     89/<- %esi 4/r32/esp
37818 $test-shift-reg-by-literal:initialize-stmt-operation:
37819     # stmt->operation = "shift-left"
37820     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37821     (copy-array Heap "shift-left" %eax)
37822     # convert
37823     c7 0/subop/copy *Curr-block-depth 0/imm32
37824     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37825     (flush _test-output-buffered-file)
37826 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37832     # check output
37833     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
37834     # . epilogue
37835     89/<- %esp 5/r32/ebp
37836     5d/pop-to-ebp
37837     c3/return
37838 
37839 test-shift-mem-by-literal:
37840     #   shift-left var 3
37841     # =>
37842     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
37843     #
37844     # . prologue
37845     55/push-ebp
37846     89/<- %ebp 4/r32/esp
37847     # setup
37848     (clear-stream _test-output-stream)
37849     (clear-stream $_test-output-buffered-file->buffer)
37850 $test-shift-mem-by-literal:initialize-type:
37851     # var type/ecx: (payload type-tree) = int
37852     68/push 0/imm32/right:null
37853     68/push 0/imm32/right:null
37854     68/push 0/imm32/left:unused
37855     68/push 1/imm32/value:int
37856     68/push 1/imm32/is-atom?:true
37857     68/push 0x11/imm32/alloc-id:fake:payload
37858     89/<- %ecx 4/r32/esp
37859 $test-shift-mem-by-literal:initialize-var1:
37860     # var var1/ecx: (payload var)
37861     68/push 0/imm32/register
37862     68/push 0/imm32/register
37863     68/push 8/imm32/stack-offset
37864     68/push 1/imm32/block-depth
37865     51/push-ecx
37866     68/push 0x11/imm32/alloc-id:fake
37867     68/push 0/imm32/name
37868     68/push 0/imm32/name
37869     68/push 0x11/imm32/alloc-id:fake:payload
37870     89/<- %ecx 4/r32/esp
37871 $test-shift-mem-by-literal:initialize-var1-name:
37872     # var1->name = "var1"
37873     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37874     (copy-array Heap "var1" %eax)
37875 $test-shift-mem-by-literal:initialize-literal-type:
37876     # var type/edx: (payload type-tree) = literal
37877     68/push 0/imm32/right:null
37878     68/push 0/imm32/right:null
37879     68/push 0/imm32/left:unused
37880     68/push 0/imm32/value:literal
37881     68/push 1/imm32/is-atom?:true
37882     68/push 0x11/imm32/alloc-id:fake:payload
37883     89/<- %edx 4/r32/esp
37884 $test-shift-mem-by-literal:initialize-literal:
37885     # var l/edx: (payload var)
37886     68/push 0/imm32/register
37887     68/push 0/imm32/register
37888     68/push 0/imm32/no-stack-offset
37889     68/push 1/imm32/block-depth
37890     52/push-edx
37891     68/push 0x11/imm32/alloc-id:fake
37892     68/push 0/imm32/name
37893     68/push 0/imm32/name
37894     68/push 0x11/imm32/alloc-id:fake:payload
37895     89/<- %edx 4/r32/esp
37896 $test-shift-mem-by-literal:initialize-literal-value:
37897     # l->name = "3"
37898     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
37899     (copy-array Heap "3" %eax)
37900 $test-shift-mem-by-literal:initialize-inouts:
37901     # var inouts/esi: (payload stmt-var) = [l]
37902     68/push 0/imm32/is-deref:false
37903     68/push 0/imm32/next
37904     68/push 0/imm32/next
37905     52/push-edx/l
37906     68/push 0x11/imm32/alloc-id:fake
37907     68/push 0x11/imm32/alloc-id:fake:payload
37908     89/<- %esi 4/r32/esp
37909     # var inouts = (handle stmt-var) = [var1, var2]
37910     68/push 0/imm32/is-deref:false
37911     56/push-esi/next
37912     68/push 0x11/imm32/alloc-id:fake
37913     51/push-ecx/var1
37914     68/push 0x11/imm32/alloc-id:fake
37915     68/push 0x11/imm32/alloc-id:fake:payload
37916     89/<- %esi 4/r32/esp
37917 $test-shift-mem-by-literal:initialize-stmt:
37918     # var stmt/esi: (addr statement)
37919     68/push 0/imm32/next
37920     68/push 0/imm32/next
37921     68/push 0/imm32/outputs
37922     68/push 0/imm32/outputs
37923     56/push-esi/inouts
37924     68/push 0x11/imm32/alloc-id:fake
37925     68/push 0/imm32/operation
37926     68/push 0/imm32/operation
37927     68/push 1/imm32/tag:stmt1
37928     89/<- %esi 4/r32/esp
37929 $test-shift-mem-by-literal:initialize-stmt-operation:
37930     # stmt->operation = "shift-left"
37931     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
37932     (copy-array Heap "shift-left" %eax)
37933     # convert
37934     c7 0/subop/copy *Curr-block-depth 0/imm32
37935     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
37936     (flush _test-output-buffered-file)
37937 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
37943     # check output
37944     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
37945     # . epilogue
37946     89/<- %esp 5/r32/ebp
37947     5d/pop-to-ebp
37948     c3/return
37949 
37950 test-compare-reg-with-reg:
37951     #   compare var1/ecx, var2/eax
37952     # =>
37953     #   39/compare %ecx 0/r32/eax
37954     #
37955     # . prologue
37956     55/push-ebp
37957     89/<- %ebp 4/r32/esp
37958     # setup
37959     (clear-stream _test-output-stream)
37960     (clear-stream $_test-output-buffered-file->buffer)
37961 $test-compare-reg-with-reg:initialize-type:
37962     # var type/ecx: (payload type-tree) = int
37963     68/push 0/imm32/right:null
37964     68/push 0/imm32/right:null
37965     68/push 0/imm32/left:unused
37966     68/push 1/imm32/value:int
37967     68/push 1/imm32/is-atom?:true
37968     68/push 0x11/imm32/alloc-id:fake:payload
37969     89/<- %ecx 4/r32/esp
37970 $test-compare-reg-with-reg:initialize-var1:
37971     # var var1/ecx: (payload var)
37972     68/push 0/imm32/register
37973     68/push 0/imm32/register
37974     68/push 0/imm32/no-stack-offset
37975     68/push 1/imm32/block-depth
37976     51/push-ecx
37977     68/push 0x11/imm32/alloc-id:fake
37978     68/push 0/imm32/name
37979     68/push 0/imm32/name
37980     68/push 0x11/imm32/alloc-id:fake:payload
37981     89/<- %ecx 4/r32/esp
37982 $test-compare-reg-with-reg:initialize-var1-name:
37983     # var1->name = "var1"
37984     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
37985     (copy-array Heap "var1" %eax)
37986 $test-compare-reg-with-reg:initialize-var1-register:
37987     # var1->register = "ecx"
37988     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
37989     (copy-array Heap "ecx" %eax)
37990 $test-compare-reg-with-reg:initialize-var2:
37991     # var var2/edx: (payload var)
37992     68/push 0/imm32/register
37993     68/push 0/imm32/register
37994     68/push 0/imm32/no-stack-offset
37995     68/push 1/imm32/block-depth
37996     ff 6/subop/push *(ecx+0x10)
37997     68/push 0x11/imm32/alloc-id:fake
37998     68/push 0/imm32/name
37999     68/push 0/imm32/name
38000     68/push 0x11/imm32/alloc-id:fake:payload
38001     89/<- %edx 4/r32/esp
38002 $test-compare-reg-with-reg:initialize-var2-name:
38003     # var2->name = "var2"
38004     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38005     (copy-array Heap "var2" %eax)
38006 $test-compare-reg-with-reg:initialize-var2-register:
38007     # var2->register = "eax"
38008     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
38009     (copy-array Heap "eax" %eax)
38010 $test-compare-reg-with-reg:initialize-inouts:
38011     # var inouts/esi: (payload stmt-var) = [var2]
38012     68/push 0/imm32/is-deref:false
38013     68/push 0/imm32/next
38014     68/push 0/imm32/next
38015     52/push-edx/var2
38016     68/push 0x11/imm32/alloc-id:fake
38017     68/push 0x11/imm32/alloc-id:fake:payload
38018     89/<- %esi 4/r32/esp
38019     # inouts = [var1, var2]
38020     68/push 0/imm32/is-deref:false
38021     56/push-esi/next
38022     68/push 0x11/imm32/alloc-id:fake
38023     51/push-ecx/var1
38024     68/push 0x11/imm32/alloc-id:fake
38025     68/push 0x11/imm32/alloc-id:fake:payload
38026     89/<- %esi 4/r32/esp
38027 $test-compare-reg-with-reg:initialize-stmt:
38028     # var stmt/esi: (addr statement)
38029     68/push 0/imm32/next
38030     68/push 0/imm32/next
38031     68/push 0/imm32/outputs
38032     68/push 0/imm32/outputs
38033     56/push-esi/inouts
38034     68/push 0x11/imm32/alloc-id:fake
38035     68/push 0/imm32/operation
38036     68/push 0/imm32/operation
38037     68/push 1/imm32/tag:stmt1
38038     89/<- %esi 4/r32/esp
38039 $test-compare-reg-with-reg:initialize-stmt-operation:
38040     # stmt->operation = "compare"
38041     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38042     (copy-array Heap "compare" %eax)
38043     # convert
38044     c7 0/subop/copy *Curr-block-depth 0/imm32
38045     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38046     (flush _test-output-buffered-file)
38047 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38053     # check output
38054     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
38055     # . epilogue
38056     89/<- %esp 5/r32/ebp
38057     5d/pop-to-ebp
38058     c3/return
38059 
38060 test-compare-mem-with-reg:
38061     #   compare var1, var2/eax
38062     # =>
38063     #   39/compare *(ebp+___) 0/r32/eax
38064     #
38065     # . prologue
38066     55/push-ebp
38067     89/<- %ebp 4/r32/esp
38068     # setup
38069     (clear-stream _test-output-stream)
38070     (clear-stream $_test-output-buffered-file->buffer)
38071 $test-compare-mem-with-reg:initialize-type:
38072     # var type/ecx: (payload type-tree) = int
38073     68/push 0/imm32/right:null
38074     68/push 0/imm32/right:null
38075     68/push 0/imm32/left:unused
38076     68/push 1/imm32/value:int
38077     68/push 1/imm32/is-atom?:true
38078     68/push 0x11/imm32/alloc-id:fake:payload
38079     89/<- %ecx 4/r32/esp
38080 $test-compare-mem-with-reg:initialize-var1:
38081     # var var1/ecx: (payload var)
38082     68/push 0/imm32/register
38083     68/push 0/imm32/register
38084     68/push 8/imm32/stack-offset
38085     68/push 1/imm32/block-depth
38086     51/push-ecx
38087     68/push 0x11/imm32/alloc-id:fake
38088     68/push 0/imm32/name
38089     68/push 0/imm32/name
38090     68/push 0x11/imm32/alloc-id:fake:payload
38091     89/<- %ecx 4/r32/esp
38092 $test-compare-mem-with-reg:initialize-var1-name:
38093     # var1->name = "var1"
38094     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38095     (copy-array Heap "var1" %eax)
38096 $test-compare-mem-with-reg:initialize-var2:
38097     # var var2/edx: (payload var)
38098     68/push 0/imm32/register
38099     68/push 0/imm32/register
38100     68/push 0/imm32/no-stack-offset
38101     68/push 1/imm32/block-depth
38102     ff 6/subop/push *(ecx+0x10)
38103     68/push 0x11/imm32/alloc-id:fake
38104     68/push 0/imm32/name
38105     68/push 0/imm32/name
38106     68/push 0x11/imm32/alloc-id:fake:payload
38107     89/<- %edx 4/r32/esp
38108 $test-compare-mem-with-reg:initialize-var2-name:
38109     # var2->name = "var2"
38110     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38111     (copy-array Heap "var2" %eax)
38112 $test-compare-mem-with-reg:initialize-var2-register:
38113     # var2->register = "eax"
38114     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
38115     (copy-array Heap "eax" %eax)
38116 $test-compare-mem-with-reg:initialize-inouts:
38117     # var inouts/esi: (payload stmt-var) = [var2]
38118     68/push 0/imm32/is-deref:false
38119     68/push 0/imm32/next
38120     68/push 0/imm32/next
38121     52/push-edx/var2
38122     68/push 0x11/imm32/alloc-id:fake
38123     68/push 0x11/imm32/alloc-id:fake:payload
38124     89/<- %esi 4/r32/esp
38125     # inouts = [var1, var2]
38126     68/push 0/imm32/is-deref:false
38127     56/push-esi/next
38128     68/push 0x11/imm32/alloc-id:fake
38129     51/push-ecx/var1
38130     68/push 0x11/imm32/alloc-id:fake
38131     68/push 0x11/imm32/alloc-id:fake:payload
38132     89/<- %esi 4/r32/esp
38133 $test-compare-mem-with-reg:initialize-stmt:
38134     # var stmt/esi: (addr statement)
38135     68/push 0/imm32/next
38136     68/push 0/imm32/next
38137     68/push 0/imm32/outputs
38138     68/push 0/imm32/outputs
38139     56/push-esi/inouts
38140     68/push 0x11/imm32/alloc-id:fake
38141     68/push 0/imm32/operation
38142     68/push 0/imm32/operation
38143     68/push 1/imm32/tag:stmt1
38144     89/<- %esi 4/r32/esp
38145 $test-compare-mem-with-reg:initialize-stmt-operation:
38146     # stmt->operation = "compare"
38147     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38148     (copy-array Heap "compare" %eax)
38149     # convert
38150     c7 0/subop/copy *Curr-block-depth 0/imm32
38151     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38152     (flush _test-output-buffered-file)
38153 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38159     # check output
38160     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
38161     # . epilogue
38162     89/<- %esp 5/r32/ebp
38163     5d/pop-to-ebp
38164     c3/return
38165 
38166 test-compare-reg-with-mem:
38167     #   compare var1/eax, var2
38168     # =>
38169     #   3b/compare<- *(ebp+___) 0/r32/eax
38170     #
38171     # . prologue
38172     55/push-ebp
38173     89/<- %ebp 4/r32/esp
38174     # setup
38175     (clear-stream _test-output-stream)
38176     (clear-stream $_test-output-buffered-file->buffer)
38177 $test-compare-reg-with-mem:initialize-type:
38178     # var type/ecx: (payload type-tree) = int
38179     68/push 0/imm32/right:null
38180     68/push 0/imm32/right:null
38181     68/push 0/imm32/left:unused
38182     68/push 1/imm32/value:int
38183     68/push 1/imm32/is-atom?:true
38184     68/push 0x11/imm32/alloc-id:fake:payload
38185     89/<- %ecx 4/r32/esp
38186 $test-compare-reg-with-mem:initialize-var1:
38187     # var var1/ecx: (payload var)
38188     68/push 0/imm32/register
38189     68/push 0/imm32/register
38190     68/push 0/imm32/no-stack-offset
38191     68/push 1/imm32/block-depth
38192     51/push-ecx
38193     68/push 0x11/imm32/alloc-id:fake
38194     68/push 0/imm32/name
38195     68/push 0/imm32/name
38196     68/push 0x11/imm32/alloc-id:fake:payload
38197     89/<- %ecx 4/r32/esp
38198 $test-compare-reg-with-mem:initialize-var1-name:
38199     # var1->name = "var1"
38200     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38201     (copy-array Heap "var1" %eax)
38202 $test-compare-reg-with-mem:initialize-var1-register:
38203     # var1->register = "eax"
38204     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38205     (copy-array Heap "eax" %eax)
38206 $test-compare-reg-with-mem:initialize-var2:
38207     # var var2/edx: (payload var)
38208     68/push 0/imm32/register
38209     68/push 0/imm32/register
38210     68/push 8/imm32/stack-offset
38211     68/push 1/imm32/block-depth
38212     ff 6/subop/push *(ecx+0x10)
38213     68/push 0x11/imm32/alloc-id:fake
38214     68/push 0/imm32/name
38215     68/push 0/imm32/name
38216     68/push 0x11/imm32/alloc-id:fake:payload
38217     89/<- %edx 4/r32/esp
38218 $test-compare-reg-with-mem:initialize-var2-name:
38219     # var2->name = "var2"
38220     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38221     (copy-array Heap "var2" %eax)
38222 $test-compare-reg-with-mem:initialize-inouts:
38223     # var inouts/esi: (payload stmt-var) = [var2]
38224     68/push 0/imm32/is-deref:false
38225     68/push 0/imm32/next
38226     68/push 0/imm32/next
38227     52/push-edx/var2
38228     68/push 0x11/imm32/alloc-id:fake
38229     68/push 0x11/imm32/alloc-id:fake:payload
38230     89/<- %esi 4/r32/esp
38231     # inouts = [var1, var2]
38232     68/push 0/imm32/is-deref:false
38233     56/push-esi/next
38234     68/push 0x11/imm32/alloc-id:fake
38235     51/push-ecx/var1
38236     68/push 0x11/imm32/alloc-id:fake
38237     68/push 0x11/imm32/alloc-id:fake:payload
38238     89/<- %esi 4/r32/esp
38239 $test-compare-reg-with-mem:initialize-stmt:
38240     # var stmt/esi: (addr statement)
38241     68/push 0/imm32/next
38242     68/push 0/imm32/next
38243     68/push 0/imm32/outputs
38244     68/push 0/imm32/outputs
38245     56/push-esi/inouts
38246     68/push 0x11/imm32/alloc-id:fake
38247     68/push 0/imm32/operation
38248     68/push 0/imm32/operation
38249     68/push 1/imm32/tag:stmt1
38250     89/<- %esi 4/r32/esp
38251 $test-compare-reg-with-mem:initialize-stmt-operation:
38252     # stmt->operation = "compare"
38253     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38254     (copy-array Heap "compare" %eax)
38255     # convert
38256     c7 0/subop/copy *Curr-block-depth 0/imm32
38257     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38258     (flush _test-output-buffered-file)
38259 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38265     # check output
38266     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
38267     # . epilogue
38268     89/<- %esp 5/r32/ebp
38269     5d/pop-to-ebp
38270     c3/return
38271 
38272 test-compare-mem-with-literal:
38273     #   compare var1, 0x34
38274     # =>
38275     #   81 7/subop/compare *(ebp+___) 0x34/imm32
38276     #
38277     # . prologue
38278     55/push-ebp
38279     89/<- %ebp 4/r32/esp
38280     # setup
38281     (clear-stream _test-output-stream)
38282     (clear-stream $_test-output-buffered-file->buffer)
38283 $test-compare-mem-with-literal:initialize-type:
38284     # var type/ecx: (payload type-tree) = int
38285     68/push 0/imm32/right:null
38286     68/push 0/imm32/right:null
38287     68/push 0/imm32/left:unused
38288     68/push 1/imm32/value:int
38289     68/push 1/imm32/is-atom?:true
38290     68/push 0x11/imm32/alloc-id:fake:payload
38291     89/<- %ecx 4/r32/esp
38292 $test-compare-mem-with-literal:initialize-var1:
38293     # var var1/ecx: (payload var)
38294     68/push 0/imm32/register
38295     68/push 0/imm32/register
38296     68/push 8/imm32/stack-offset
38297     68/push 1/imm32/block-depth
38298     51/push-ecx
38299     68/push 0x11/imm32/alloc-id:fake
38300     68/push 0/imm32/name
38301     68/push 0/imm32/name
38302     68/push 0x11/imm32/alloc-id:fake:payload
38303     89/<- %ecx 4/r32/esp
38304 $test-compare-mem-with-literal:initialize-var1-name:
38305     # var1->name = "var1"
38306     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38307     (copy-array Heap "var1" %eax)
38308 $test-compare-mem-with-literal:initialize-literal-type:
38309     # var type/edx: (payload type-tree) = literal
38310     68/push 0/imm32/right:null
38311     68/push 0/imm32/right:null
38312     68/push 0/imm32/left:unused
38313     68/push 0/imm32/value:literal
38314     68/push 1/imm32/is-atom?:true
38315     68/push 0x11/imm32/alloc-id:fake:payload
38316     89/<- %edx 4/r32/esp
38317 $test-compare-mem-with-literal:initialize-literal:
38318     # var l/edx: (payload var)
38319     68/push 0/imm32/register
38320     68/push 0/imm32/register
38321     68/push 0/imm32/no-stack-offset
38322     68/push 1/imm32/block-depth
38323     52/push-edx
38324     68/push 0x11/imm32/alloc-id:fake
38325     68/push 0/imm32/name
38326     68/push 0/imm32/name
38327     68/push 0x11/imm32/alloc-id:fake:payload
38328     89/<- %edx 4/r32/esp
38329 $test-compare-mem-with-literal:initialize-literal-value:
38330     # l->name = "0x34"
38331     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38332     (copy-array Heap "0x34" %eax)
38333 $test-compare-mem-with-literal:initialize-inouts:
38334     # var inouts/esi: (payload stmt-var) = [l]
38335     68/push 0/imm32/is-deref:false
38336     68/push 0/imm32/next
38337     68/push 0/imm32/next
38338     52/push-edx/l
38339     68/push 0x11/imm32/alloc-id:fake
38340     68/push 0x11/imm32/alloc-id:fake:payload
38341     89/<- %esi 4/r32/esp
38342     # var inouts = (handle stmt-var) = [var1, var2]
38343     68/push 0/imm32/is-deref:false
38344     56/push-esi/next
38345     68/push 0x11/imm32/alloc-id:fake
38346     51/push-ecx/var1
38347     68/push 0x11/imm32/alloc-id:fake
38348     68/push 0x11/imm32/alloc-id:fake:payload
38349     89/<- %esi 4/r32/esp
38350 $test-compare-mem-with-literal:initialize-stmt:
38351     # var stmt/esi: (addr statement)
38352     68/push 0/imm32/next
38353     68/push 0/imm32/next
38354     68/push 0/imm32/outputs
38355     68/push 0/imm32/outputs
38356     56/push-esi/inouts
38357     68/push 0x11/imm32/alloc-id:fake
38358     68/push 0/imm32/operation
38359     68/push 0/imm32/operation
38360     68/push 1/imm32/tag:stmt1
38361     89/<- %esi 4/r32/esp
38362 $test-compare-mem-with-literal:initialize-stmt-operation:
38363     # stmt->operation = "compare"
38364     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38365     (copy-array Heap "compare" %eax)
38366     # convert
38367     c7 0/subop/copy *Curr-block-depth 0/imm32
38368     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38369     (flush _test-output-buffered-file)
38370 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38376     # check output
38377     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
38378     # . epilogue
38379     89/<- %esp 5/r32/ebp
38380     5d/pop-to-ebp
38381     c3/return
38382 
38383 test-compare-eax-with-literal:
38384     #   compare var1/eax 0x34
38385     # =>
38386     #   3d/compare-eax-with 0x34/imm32
38387     #
38388     # . prologue
38389     55/push-ebp
38390     89/<- %ebp 4/r32/esp
38391     # setup
38392     (clear-stream _test-output-stream)
38393     (clear-stream $_test-output-buffered-file->buffer)
38394 $test-compare-eax-with-literal:initialize-type:
38395     # var type/ecx: (payload type-tree) = int
38396     68/push 0/imm32/right:null
38397     68/push 0/imm32/right:null
38398     68/push 0/imm32/left:unused
38399     68/push 1/imm32/value:int
38400     68/push 1/imm32/is-atom?:true
38401     68/push 0x11/imm32/alloc-id:fake:payload
38402     89/<- %ecx 4/r32/esp
38403 $test-compare-eax-with-literal:initialize-var1:
38404     # var var1/ecx: (payload var)
38405     68/push 0/imm32/register
38406     68/push 0/imm32/register
38407     68/push 0/imm32/no-stack-offset
38408     68/push 1/imm32/block-depth
38409     51/push-ecx
38410     68/push 0x11/imm32/alloc-id:fake
38411     68/push 0/imm32/name
38412     68/push 0/imm32/name
38413     68/push 0x11/imm32/alloc-id:fake:payload
38414     89/<- %ecx 4/r32/esp
38415 $test-compare-eax-with-literal:initialize-var1-name:
38416     # var1->name = "var1"
38417     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38418     (copy-array Heap "var1" %eax)
38419 $test-compare-eax-with-literal:initialize-var1-register:
38420     # v->register = "eax"
38421     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38422     (copy-array Heap "eax" %eax)
38423 $test-compare-eax-with-literal:initialize-literal-type:
38424     # var type/edx: (payload type-tree) = literal
38425     68/push 0/imm32/right:null
38426     68/push 0/imm32/right:null
38427     68/push 0/imm32/left:unused
38428     68/push 0/imm32/value:literal
38429     68/push 1/imm32/is-atom?:true
38430     68/push 0x11/imm32/alloc-id:fake:payload
38431     89/<- %edx 4/r32/esp
38432 $test-compare-eax-with-literal:initialize-literal:
38433     # var l/edx: (payload var)
38434     68/push 0/imm32/register
38435     68/push 0/imm32/register
38436     68/push 0/imm32/no-stack-offset
38437     68/push 1/imm32/block-depth
38438     52/push-edx
38439     68/push 0x11/imm32/alloc-id:fake
38440     68/push 0/imm32/name
38441     68/push 0/imm32/name
38442     68/push 0x11/imm32/alloc-id:fake:payload
38443     89/<- %edx 4/r32/esp
38444 $test-compare-eax-with-literal:initialize-literal-value:
38445     # l->name = "0x34"
38446     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38447     (copy-array Heap "0x34" %eax)
38448 $test-compare-eax-with-literal:initialize-inouts:
38449     # var inouts/esi: (payload stmt-var) = [l]
38450     68/push 0/imm32/is-deref:false
38451     68/push 0/imm32/next
38452     68/push 0/imm32/next
38453     52/push-edx/l
38454     68/push 0x11/imm32/alloc-id:fake
38455     68/push 0x11/imm32/alloc-id:fake:payload
38456     89/<- %esi 4/r32/esp
38457     # var inouts = (handle stmt-var) = [var1, var2]
38458     68/push 0/imm32/is-deref:false
38459     56/push-esi/next
38460     68/push 0x11/imm32/alloc-id:fake
38461     51/push-ecx/var1
38462     68/push 0x11/imm32/alloc-id:fake
38463     68/push 0x11/imm32/alloc-id:fake:payload
38464     89/<- %esi 4/r32/esp
38465 $test-compare-eax-with-literal:initialize-stmt:
38466     # var stmt/esi: (addr statement)
38467     68/push 0/imm32/next
38468     68/push 0/imm32/next
38469     68/push 0/imm32/outputs
38470     68/push 0/imm32/outputs
38471     56/push-esi/inouts
38472     68/push 0x11/imm32/alloc-id:fake
38473     68/push 0/imm32/operation
38474     68/push 0/imm32/operation
38475     68/push 1/imm32/tag:stmt1
38476     89/<- %esi 4/r32/esp
38477 $test-compare-eax-with-literal:initialize-stmt-operation:
38478     # stmt->operation = "compare"
38479     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38480     (copy-array Heap "compare" %eax)
38481     # convert
38482     c7 0/subop/copy *Curr-block-depth 0/imm32
38483     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38484     (flush _test-output-buffered-file)
38485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38491     # check output
38492     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
38493     # . epilogue
38494     89/<- %esp 5/r32/ebp
38495     5d/pop-to-ebp
38496     c3/return
38497 
38498 test-compare-reg-with-literal:
38499     #   compare var1/ecx 0x34
38500     # =>
38501     #   81 7/subop/compare %ecx 0x34/imm32
38502     #
38503     # . prologue
38504     55/push-ebp
38505     89/<- %ebp 4/r32/esp
38506     # setup
38507     (clear-stream _test-output-stream)
38508     (clear-stream $_test-output-buffered-file->buffer)
38509 $test-compare-reg-with-literal:initialize-type:
38510     # var type/ecx: (payload type-tree) = int
38511     68/push 0/imm32/right:null
38512     68/push 0/imm32/right:null
38513     68/push 0/imm32/left:unused
38514     68/push 1/imm32/value:int
38515     68/push 1/imm32/is-atom?:true
38516     68/push 0x11/imm32/alloc-id:fake:payload
38517     89/<- %ecx 4/r32/esp
38518 $test-compare-reg-with-literal:initialize-var1:
38519     # var var1/ecx: (payload var)
38520     68/push 0/imm32/register
38521     68/push 0/imm32/register
38522     68/push 0/imm32/no-stack-offset
38523     68/push 1/imm32/block-depth
38524     51/push-ecx
38525     68/push 0x11/imm32/alloc-id:fake
38526     68/push 0/imm32/name
38527     68/push 0/imm32/name
38528     68/push 0x11/imm32/alloc-id:fake:payload
38529     89/<- %ecx 4/r32/esp
38530 $test-compare-reg-with-literal:initialize-var1-name:
38531     # var1->name = "var1"
38532     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38533     (copy-array Heap "var1" %eax)
38534 $test-compare-reg-with-literal:initialize-var1-register:
38535     # v->register = "ecx"
38536     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
38537     (copy-array Heap "ecx" %eax)
38538 $test-compare-reg-with-literal:initialize-literal-type:
38539     # var type/edx: (payload type-tree) = literal
38540     68/push 0/imm32/right:null
38541     68/push 0/imm32/right:null
38542     68/push 0/imm32/left:unused
38543     68/push 0/imm32/value:literal
38544     68/push 1/imm32/is-atom?:true
38545     68/push 0x11/imm32/alloc-id:fake:payload
38546     89/<- %edx 4/r32/esp
38547 $test-compare-reg-with-literal:initialize-literal:
38548     # var l/edx: (payload var)
38549     68/push 0/imm32/register
38550     68/push 0/imm32/register
38551     68/push 0/imm32/no-stack-offset
38552     68/push 1/imm32/block-depth
38553     52/push-edx
38554     68/push 0x11/imm32/alloc-id:fake
38555     68/push 0/imm32/name
38556     68/push 0/imm32/name
38557     68/push 0x11/imm32/alloc-id:fake:payload
38558     89/<- %edx 4/r32/esp
38559 $test-compare-reg-with-literal:initialize-literal-value:
38560     # l->name = "0x34"
38561     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
38562     (copy-array Heap "0x34" %eax)
38563 $test-compare-reg-with-literal:initialize-inouts:
38564     # var inouts/esi: (payload stmt-var) = [l]
38565     68/push 0/imm32/is-deref:false
38566     68/push 0/imm32/next
38567     68/push 0/imm32/next
38568     52/push-edx/l
38569     68/push 0x11/imm32/alloc-id:fake
38570     68/push 0x11/imm32/alloc-id:fake:payload
38571     89/<- %esi 4/r32/esp
38572     # var inouts = (handle stmt-var) = [var1, var2]
38573     68/push 0/imm32/is-deref:false
38574     56/push-esi/next
38575     68/push 0x11/imm32/alloc-id:fake
38576     51/push-ecx/var1
38577     68/push 0x11/imm32/alloc-id:fake
38578     68/push 0x11/imm32/alloc-id:fake:payload
38579     89/<- %esi 4/r32/esp
38580 $test-compare-reg-with-literal:initialize-stmt:
38581     # var stmt/esi: (addr statement)
38582     68/push 0/imm32/next
38583     68/push 0/imm32/next
38584     68/push 0/imm32/outputs
38585     68/push 0/imm32/outputs
38586     56/push-esi/inouts
38587     68/push 0x11/imm32/alloc-id:fake
38588     68/push 0/imm32/operation
38589     68/push 0/imm32/operation
38590     68/push 1/imm32/tag:stmt1
38591     89/<- %esi 4/r32/esp
38592 $test-compare-reg-with-literal:initialize-stmt-operation:
38593     # stmt->operation = "compare"
38594     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38595     (copy-array Heap "compare" %eax)
38596     # convert
38597     c7 0/subop/copy *Curr-block-depth 0/imm32
38598     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
38599     (flush _test-output-buffered-file)
38600 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38606     # check output
38607     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
38608     # . epilogue
38609     89/<- %esp 5/r32/ebp
38610     5d/pop-to-ebp
38611     c3/return
38612 
38613 test-emit-subx-stmt-function-call:
38614     # Call a function on a variable on the stack.
38615     #   f foo
38616     # =>
38617     #   (f *(ebp-8))
38618     # (Changing the function name supports overloading in general, but here it
38619     # just serves to help disambiguate things.)
38620     #
38621     # There's a variable on the var stack as follows:
38622     #   name: 'foo'
38623     #   type: int
38624     #   stack-offset: -8
38625     #
38626     # There's nothing in primitives.
38627     #
38628     # We don't perform any checking here on the type of 'f'.
38629     #
38630     # . prologue
38631     55/push-ebp
38632     89/<- %ebp 4/r32/esp
38633     # setup
38634     (clear-stream _test-output-stream)
38635     (clear-stream $_test-output-buffered-file->buffer)
38636 $test-emit-subx-function-call:initialize-type:
38637     # var type/ecx: (payload type-tree) = int
38638     68/push 0/imm32/right:null
38639     68/push 0/imm32/right:null
38640     68/push 0/imm32/left:unused
38641     68/push 1/imm32/value:int
38642     68/push 1/imm32/is-atom?:true
38643     68/push 0x11/imm32/alloc-id:fake:payload
38644     89/<- %ecx 4/r32/esp
38645 $test-emit-subx-function-call:initialize-var:
38646     # var var-foo/ecx: (payload var) = var(type)
38647     68/push 0/imm32/no-register
38648     68/push 0/imm32/no-register
38649     68/push -8/imm32/stack-offset
38650     68/push 1/imm32/block-depth
38651     51/push-ecx/type
38652     68/push 0x11/imm32/alloc-id:fake
38653     68/push 0/imm32/name
38654     68/push 0/imm32/name
38655     68/push 0x11/imm32/alloc-id:fake:payload
38656     89/<- %ecx 4/r32/esp
38657 $test-emit-subx-function-call:initialize-var-name:
38658     # var-foo->name = "foo"
38659     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38660     (copy-array Heap "foo" %eax)
38661 $test-emit-subx-function-call:initialize-stmt-var:
38662     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38663     68/push 0/imm32/is-deref:false
38664     68/push 0/imm32/next
38665     68/push 0/imm32/next
38666     51/push-ecx/var-foo
38667     68/push 0x11/imm32/alloc-id:fake
38668     68/push 0x11/imm32/alloc-id:fake:payload
38669     89/<- %ebx 4/r32/esp
38670 $test-emit-subx-function-call:initialize-stmt:
38671     # var stmt/esi: (addr statement)
38672     68/push 0/imm32/no-outputs
38673     68/push 0/imm32/no-outputs
38674     53/push-ebx/inouts
38675     68/push 0x11/imm32/alloc-id:fake
38676     68/push 0/imm32/operation
38677     68/push 0/imm32/operation
38678     68/push 1/imm32/tag
38679     89/<- %esi 4/r32/esp
38680 $test-emit-subx-function-call:initialize-stmt-operation:
38681     # stmt->operation = "f"
38682     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38683     (copy-array Heap "f" %eax)
38684     # convert
38685     c7 0/subop/copy *Curr-block-depth 0/imm32
38686     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
38687     (flush _test-output-buffered-file)
38688 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38694     # check output
38695     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
38696     # . epilogue
38697     89/<- %esp 5/r32/ebp
38698     5d/pop-to-ebp
38699     c3/return
38700 
38701 test-emit-subx-stmt-function-call-with-literal-arg:
38702     # Call a function on a literal.
38703     #   f 0x34
38704     # =>
38705     #   (f2 0x34)
38706     #
38707     # . prologue
38708     55/push-ebp
38709     89/<- %ebp 4/r32/esp
38710     # setup
38711     (clear-stream _test-output-stream)
38712     (clear-stream $_test-output-buffered-file->buffer)
38713 $test-emit-subx-function-call-with-literal-arg:initialize-type:
38714     # var type/ecx: (payload type-tree) = int
38715     68/push 0/imm32/right:null
38716     68/push 0/imm32/right:null
38717     68/push 0/imm32/left:unused
38718     68/push 0/imm32/value:literal
38719     68/push 1/imm32/is-atom?:true
38720     68/push 0x11/imm32/alloc-id:fake:payload
38721     89/<- %ecx 4/r32/esp
38722 $test-emit-subx-function-call-with-literal-arg:initialize-var:
38723     # var var-foo/ecx: (payload var) = var(lit)
38724     68/push 0/imm32/no-register
38725     68/push 0/imm32/no-register
38726     68/push 0/imm32/no-stack-offset
38727     68/push 1/imm32/block-depth
38728     51/push-ecx/type
38729     68/push 0x11/imm32/alloc-id:fake
38730     68/push 0/imm32/name
38731     68/push 0/imm32/name
38732     68/push 0x11/imm32/alloc-id:fake:payload
38733     89/<- %ecx 4/r32/esp
38734 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
38735     # var-foo->name = "0x34"
38736     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
38737     (copy-array Heap "0x34" %eax)
38738 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
38739     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
38740     68/push 0/imm32/is-deref:false
38741     68/push 0/imm32/next
38742     68/push 0/imm32/next
38743     51/push-ecx/var-foo
38744     68/push 0x11/imm32/alloc-id:fake
38745     68/push 0x11/imm32/alloc-id:fake:payload
38746     89/<- %ebx 4/r32/esp
38747 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
38748     # var stmt/esi: (addr statement)
38749     68/push 0/imm32/no-outputs
38750     68/push 0/imm32/no-outputs
38751     53/push-ebx/inouts
38752     68/push 0x11/imm32/alloc-id:fake
38753     68/push 0/imm32/operation
38754     68/push 0/imm32/operation
38755     68/push 1/imm32/tag
38756     89/<- %esi 4/r32/esp
38757 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
38758     # stmt->operation = "f"
38759     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
38760     (copy-array Heap "f" %eax)
38761     # convert
38762     c7 0/subop/copy *Curr-block-depth 0/imm32
38763     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
38764     (flush _test-output-buffered-file)
38765 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
38771     # check output
38772     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
38773     # . epilogue
38774     89/<- %esp 5/r32/ebp
38775     5d/pop-to-ebp
38776     c3/return
38777 
38778 emit-indent:  # out: (addr buffered-file), n: int
38779     # . prologue
38780     55/push-ebp
38781     89/<- %ebp 4/r32/esp
38782     # . save registers
38783     50/push-eax
38784     # var i/eax: int = n
38785     8b/-> *(ebp+0xc) 0/r32/eax
38786     {
38787       # if (i <= 0) break
38788       3d/compare-eax-with 0/imm32
38789       7e/jump-if-<= break/disp8
38790       (write-buffered *(ebp+8) "  ")
38791       48/decrement-eax
38792       eb/jump loop/disp8
38793     }
38794 $emit-indent:end:
38795     # . restore registers
38796     58/pop-to-eax
38797     # . epilogue
38798     89/<- %esp 5/r32/ebp
38799     5d/pop-to-ebp
38800     c3/return
38801 
38802 emit-subx-prologue:  # out: (addr buffered-file)
38803     # . prologue
38804     55/push-ebp
38805     89/<- %ebp 4/r32/esp
38806     #
38807     (write-buffered *(ebp+8) "  # . prologue\n")
38808     (write-buffered *(ebp+8) "  55/push-ebp\n")
38809     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
38810 $emit-subx-prologue:end:
38811     # . epilogue
38812     89/<- %esp 5/r32/ebp
38813     5d/pop-to-ebp
38814     c3/return
38815 
38816 emit-subx-epilogue:  # out: (addr buffered-file)
38817     # . prologue
38818     55/push-ebp
38819     89/<- %ebp 4/r32/esp
38820     #
38821     (write-buffered *(ebp+8) "  # . epilogue\n")
38822     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
38823     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
38824     (write-buffered *(ebp+8) "  c3/return\n")
38825 $emit-subx-epilogue:end:
38826     # . epilogue
38827     89/<- %esp 5/r32/ebp
38828     5d/pop-to-ebp
38829     c3/return