https://github.com/akkartik/mu/blob/master/apps/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> result/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.
   39 #
   40 # Blocks mostly consist of statements.
   41 #
   42 # Statements mostly consist of a name, optional inputs and optional outputs.
   43 #
   44 # Statement inputs are variables or literals. Variables need to specify type
   45 # (and storage) the first time they're mentioned but not later.
   46 #
   47 # Statement outputs, like function outputs, must be variables in registers.
   48 #
   49 # Statement names must be either primitives or user-defined functions.
   50 #
   51 # Primitives can write to any register.
   52 # User-defined functions only write to hard-coded registers. Outputs of each
   53 # call must have the same registers as in the function definition.
   54 #
   55 # There are some other statement types:
   56 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   57 #     prefixed with a label name and ':'
   58 #       - {
   59 #           ...
   60 #         }
   61 #       - foo: {
   62 #           ...
   63 #         }
   64 #
   65 #   - variable definitions on the stack. E.g.:
   66 #       - var foo: int
   67 #       - var bar: (array int 3)
   68 #     There's no initializer; variables are automatically initialized.
   69 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   70 #
   71 #   - variables definitions in a register. E.g.:
   72 #       - var foo/eax: int <- add bar 1
   73 #     The initializer is mandatory and must be a valid instruction that writes
   74 #     a single output to the right register. In practice registers will
   75 #     usually be either initialized by primitives or copied from eax.
   76 #       - var eax: int <- foo bar quux
   77 #         var floo/ecx: int <- copy eax
   78 #
   79 # Still todo:
   80 #   global variables
   81 #   union types
   82 #
   83 # Formal types:
   84 #   A program is a linked list of functions
   85 #   A function contains:
   86 #     name: (handle array byte)
   87 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   88 #       data: (handle var)
   89 #       next: (handle list)
   90 #     outputs: linked list of vars
   91 #       data: (handle var)
   92 #       next: (handle list)
   93 #     body: (handle block)
   94 #   A var-type contains:
   95 #     name: (handle array byte)
   96 #     type: (handle type-tree)
   97 #
   98 #   A statement can be:
   99 #     tag 0: a block
  100 #     tag 1: a simple statement (stmt1)
  101 #     tag 2: a variable defined on the stack
  102 #     tag 3: a variable defined in a register
  103 #
  104 #   A block contains:
  105 #     tag: 0
  106 #     statements: (handle list stmt)
  107 #     name: (handle array byte) -- starting with '$'
  108 #
  109 #   A regular statement contains:
  110 #     tag: 1
  111 #     operation: (handle array byte)
  112 #     inouts: (handle list operand)
  113 #     outputs: (handle list var)
  114 #
  115 #   A variable defined on the stack contains:
  116 #     tag: 2
  117 #     name: (handle array byte)
  118 #     type: (handle type-tree)
  119 #
  120 #   A variable defined in a register contains:
  121 #     tag: 3
  122 #     name: (handle array byte)
  123 #     type: (handle type-tree)
  124 #     reg: (handle array byte)
  125 
  126 # == Translation: managing the stack
  127 # Now that we know what the language looks like in the large, let's think
  128 # about how translation happens from the bottom up. One crucial piece of the
  129 # puzzle is how Mu will clean up variables defined on the stack for you.
  130 #
  131 # Assume that we maintain a 'functions' list while parsing source code. And a
  132 # 'primitives' list is a global constant. Both these contain enough information
  133 # to perform type-checking on function calls or primitive statements, respectively.
  134 #
  135 # Defining variables pushes them on a stack with the current block depth and
  136 # enough information about their location (stack offset or register).
  137 # Starting a block increments the current block id.
  138 # Each statement now has enough information to emit code for it.
  139 # Ending a block is where the magic happens:
  140 #   pop all variables at the current block depth
  141 #   emit code to restore all register variables introduced at the current depth
  142 #   emit code to clean up all stack variables at the current depth (just increment esp)
  143 #   decrement the current block depth
  144 #
  145 # Formal types:
  146 #   live-vars: stack of vars
  147 #   var:
  148 #     name: (handle array byte)
  149 #     type: (handle type-tree)
  150 #     block: int
  151 #     stack-offset: int  (added to ebp)
  152 #     register: (handle array byte)
  153 #       either usual register names
  154 #       or '*' to indicate any register
  155 #   At most one of stack-offset or register-index must be non-zero.
  156 #   A register of '*' designates a variable _template_. Only legal in formal
  157 #   parameters for primitives.
  158 
  159 # == Translating a single function call
  160 # This one's easy. Assuming we've already checked things, we just drop the
  161 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  162 #
  163 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  164 # =>
  165 # (name inout1 inout2 inout3)
  166 #
  167 # Formal types:
  168 #   functions: linked list of info
  169 #     name: (handle array byte)
  170 #     inouts: linked list of vars
  171 #     outputs: linked list of vars
  172 #     body: block (linked list of statements)
  173 
  174 # == Translating a single primitive instruction
  175 # A second crucial piece of the puzzle is how Mu converts fairly regular
  176 # primitives with their uniform syntax to SubX instructions with their gnarly
  177 # x86 details.
  178 #
  179 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  180 # them.
  181 # SubX instructions have rm32 and r32 operands.
  182 # The translation between them covers almost all the possibilities.
  183 #   Instructions with 1 inout may turn into ones with 1 rm32
  184 #     (e.g. incrementing a var on the stack)
  185 #   Instructions with 1 output may turn into ones with 1 rm32
  186 #     (e.g. incrementing a var in a register)
  187 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  188 #     (e.g. adding a var to a reg)
  189 #   2 inouts may turn into 1 rm32 and 1 r32
  190 #     (e.g. adding a reg to a var)
  191 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  192 #     (e.g. adding a constant to a var)
  193 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  194 #     (e.g. adding a constant to a reg)
  195 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  196 #     (special-case: divide edx:eax by a var or reg)
  197 # Observations:
  198 #   We always emit rm32. It may be the first inout or the first output.
  199 #   We may emit r32 or imm32 or neither.
  200 #   When we emit r32 it may come from first inout or second inout or first output.
  201 #
  202 # Accordingly, the formal data structure for a primitive looks like this:
  203 #   primitives: linked list of info
  204 #     name: (handle array byte)
  205 #     mu-inouts: linked list of vars to check
  206 #     mu-outputs: linked list of vars to check; at most a singleton
  207 #     subx-name: (handle array byte)
  208 #     subx-rm32: enum arg-location
  209 #     subx-r32: enum arg-location
  210 #     subx-imm32: enum arg-location
  211 #     subx-imm8: enum arg-location
  212 #     subx-disp32: enum arg-location
  213 #     subx-xm32: enum arg-location
  214 #     subx-x32: enum arg-location
  215 #   arg-location: enum
  216 #     0 means none
  217 #     1 means first inout
  218 #     2 means second inout
  219 #     3 means first output
  220 
  221 # == Translating a block
  222 # Emit block name if necessary
  223 # Emit '{'
  224 # When you encounter a statement, emit it as above
  225 # When you encounter a variable declaration
  226 #   emit any code needed for it (bzeros)
  227 #   push it on the var stack
  228 #   update register dict if necessary
  229 # When you encounter '}'
  230 #   While popping variables off the var stack until block id changes
  231 #     Emit code needed to clean up the stack
  232 #       either increment esp
  233 #       or pop into appropriate register
  234 
  235 # The rest is straightforward.
  236 
  237 == data
  238 
  239 Program:
  240 _Program-functions:  # (handle function)
  241   0/imm32
  242 _Program-functions->payload:
  243   0/imm32
  244 _Program-types:  # (handle typeinfo)
  245   0/imm32
  246 _Program-types->payload:
  247   0/imm32
  248 _Program-signatures:  # (handle function)
  249   0/imm32
  250 _Program-signatures->payload:
  251   0/imm32
  252 
  253 # Some constants for simulating the data structures described above.
  254 # Many constants here come with a type in a comment.
  255 #
  256 # Sometimes the type is of the value at that offset for the given type. For
  257 # example, if you start at a function record and move forward Function-inouts
  258 # bytes, you'll find a (handle list var).
  259 #
  260 # At other times, the type is of the constant itself. For example, the type of
  261 # the constant Function-size is (addr int). To get the size of a function,
  262 # look in *Function-size.
  263 
  264 Function-name:  # (handle array byte)
  265   0/imm32
  266 Function-inouts:  # (handle list var)
  267   8/imm32
  268 Function-outputs:  # (handle list var)
  269   0x10/imm32
  270 Function-body:  # (handle block)
  271   0x18/imm32
  272 Function-next:  # (handle function)
  273   0x20/imm32
  274 Function-size:  # (addr int)
  275   0x28/imm32/40
  276 
  277 Primitive-name:  # (handle array byte)
  278   0/imm32
  279 Primitive-inouts:  # (handle list var)
  280   8/imm32
  281 Primitive-outputs:  # (handle list var)
  282   0x10/imm32
  283 Primitive-subx-name:  # (handle array byte)
  284   0x18/imm32
  285 Primitive-subx-rm32:  # enum arg-location
  286   0x20/imm32
  287 Primitive-subx-r32:  # enum arg-location
  288   0x24/imm32
  289 Primitive-subx-imm32:  # enum arg-location
  290   0x28/imm32
  291 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  292   0x2c/imm32
  293 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  294   0x30/imm32
  295 Primitive-subx-xm32:  # enum arg-location
  296   0x34/imm32
  297 Primitive-subx-x32:  # enum arg-location
  298   0x38/imm32
  299 Primitive-next:  # (handle function)
  300   0x3c/imm32
  301 Primitive-size:  # (addr int)
  302   0x44/imm32/68
  303 
  304 Stmt-tag:  # int
  305   0/imm32
  306 
  307 Block-stmts:  # (handle list stmt)
  308   4/imm32
  309 Block-var:  # (handle var)
  310   0xc/imm32
  311 
  312 Stmt1-operation:  # (handle array byte)
  313   4/imm32
  314 Stmt1-inouts:  # (handle stmt-var)
  315   0xc/imm32
  316 Stmt1-outputs:  # (handle stmt-var)
  317   0x14/imm32
  318 
  319 Vardef-var:  # (handle var)
  320   4/imm32
  321 
  322 Regvardef-operation:  # (handle array byte)
  323   4/imm32
  324 Regvardef-inouts:  # (handle stmt-var)
  325   0xc/imm32
  326 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  327   0x14/imm32
  328 
  329 Stmt-size:  # (addr int)
  330   0x1c/imm32
  331 
  332 Var-name:  # (handle array byte)
  333   0/imm32
  334 Var-type:  # (handle type-tree)
  335   8/imm32
  336 Var-block-depth:  # int -- not available until code-generation time
  337   0x10/imm32
  338 Var-offset:  # int -- not available until code-generation time
  339   0x14/imm32
  340 Var-register:  # (handle array byte) -- name of a register
  341   0x18/imm32
  342 Var-size:  # (addr int)
  343   0x20/imm32
  344 
  345 List-value:  # (handle _)
  346   0/imm32
  347 List-next:  # (handle list _)
  348   8/imm32
  349 List-size:  # (addr int)
  350   0x10/imm32
  351 
  352 # A stmt-var is like a list of vars with call-site specific metadata
  353 Stmt-var-value:  # (handle var)
  354   0/imm32
  355 Stmt-var-next:  # (handle stmt-var)
  356   8/imm32
  357 Stmt-var-is-deref:  # boolean
  358   0x10/imm32
  359 Stmt-var-size:  # (addr int)
  360   0x14/imm32
  361 
  362 # A live-var is a var augmented with information needed for tracking live
  363 # variables.
  364 Live-var-value:  # (handle var)
  365   0/imm32
  366 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  367   8/imm32
  368 Live-var-size:  # (addr int)
  369   0xc/imm32
  370 
  371 # Types are expressed as trees (s-expressions) of type-ids (ints).
  372 
  373 Type-tree-is-atom:  # boolean
  374   0/imm32
  375 # if is-atom?
  376 Type-tree-value:  # type-id
  377   4/imm32
  378 Type-tree-value-size:  # int (for static data structure sizes)
  379   8/imm32
  380 Type-tree-parameter-name:  # (handle array byte) for type parameters
  381   8/imm32
  382 # unless is-atom?
  383 Type-tree-left:  # (addr type-tree)
  384   4/imm32
  385 Type-tree-right:  # (addr type-tree)
  386   0xc/imm32
  387 #
  388 Type-tree-size:  # (addr int)
  389   0x14/imm32
  390 
  391 # Types
  392 
  393 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  394 Type-id:  # (stream (addr array byte))
  395   0/imm32/write  # initialized later from Primitive-type-ids
  396   0/imm32/read
  397   0x100/imm32/size
  398   # data
  399   0/imm32  # 0 reserved for literals; value is just the name
  400            # Not to be used directly, so we don't include a name here.
  401   "int"/imm32  # 1
  402   "addr"/imm32  # 2
  403   "array"/imm32  # 3
  404   "handle"/imm32  # 4
  405   "boolean"/imm32  # 5
  406   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  407            # Not to be used directly, so we don't include a name here.
  408   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  409   # 0x20
  410   "byte"/imm32  # 8
  411   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  412            # Not to be used directly, so we don't include a name here.
  413   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  414            # Not to be used directly, so we don't include a name here.
  415   "stream"/imm32  # 11
  416   "slice"/imm32  # 12
  417   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  418   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  419                     # only 4-byte graphemes in utf-8 are currently supported;
  420                     # unclear how we should deal with larger clusters.
  421   "float"/imm32     # 15
  422   # Keep Primitive-type-ids in sync if you add types here.
  423   # 0x40
  424   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  425   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  426   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  427   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  428   0/imm32 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 
  431 Primitive-type-ids:  # (addr int)
  432   0x40
  433 
  434 # == Type definitions
  435 # Program->types contains some typeinfo for each type definition.
  436 # Types contain vars with types, but can't specify registers.
  437 Typeinfo-id:  # type-id
  438   0/imm32
  439 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  440   4/imm32
  441 # Total size must be >= 0
  442 # During parsing it may take on two additional values:
  443 #   -2: not yet initialized
  444 #   -1: in process of being computed
  445 # See populate-mu-type-sizes for details.
  446 Typeinfo-total-size-in-bytes:  # int
  447   0xc/imm32
  448 Typeinfo-next:  # (handle typeinfo)
  449   0x10/imm32
  450 Typeinfo-size:  # (addr int)
  451   0x18/imm32
  452 
  453 # Each entry in the typeinfo->fields table has a pointer to a string and a
  454 # pointer to a typeinfo-entry.
  455 Typeinfo-fields-row-size:  # (addr int)
  456   0x10/imm32
  457 
  458 # typeinfo-entry objects have information about a field in a single record type
  459 #
  460 # each field of a type is represented using two var's:
  461 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  462 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  463 # computing the output happens after parsing; in the meantime we preserve the
  464 # order of fields in the 'index' field.
  465 Typeinfo-entry-input-var:  # (handle var)
  466   0/imm32
  467 Typeinfo-entry-index:  # int
  468   8/imm32
  469 Typeinfo-entry-output-var:  # (handle var)
  470   0xc/imm32
  471 Typeinfo-entry-size:  # (addr int)
  472   0x14/imm32
  473 
  474 == code
  475 
  476 Entry:
  477     # . prologue
  478     89/<- %ebp 4/r32/esp
  479     (new-segment *Heap-size Heap)
  480     # if (argv[1] == "test') run-tests()
  481     {
  482       # if (argc <= 1) break
  483       81 7/subop/compare *ebp 1/imm32
  484       7e/jump-if-<= break/disp8
  485       # if (argv[1] != "test") break
  486       (kernel-string-equal? *(ebp+8) "test")  # => eax
  487       3d/compare-eax-and 0/imm32/false
  488       74/jump-if-= break/disp8
  489       #
  490       (run-tests)
  491       # syscall(exit, *Num-test-failures)
  492       8b/-> *Num-test-failures 3/r32/ebx
  493       eb/jump $mu-main:end/disp8
  494     }
  495     # otherwise convert Stdin
  496     (convert-mu Stdin Stdout Stderr 0)
  497     (flush Stdout)
  498     # syscall(exit, 0)
  499     bb/copy-to-ebx 0/imm32
  500 $mu-main:end:
  501     e8/call syscall_exit/disp32
  502 
  503 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  504     # . prologue
  505     55/push-ebp
  506     89/<- %ebp 4/r32/esp
  507     # . save registers
  508     50/push-eax
  509     # initialize global data structures
  510     c7 0/subop/copy *Next-block-index 1/imm32
  511     8b/-> *Primitive-type-ids 0/r32/eax
  512     89/<- *Type-id 0/r32/eax  # stream-write
  513     c7 0/subop/copy *_Program-functions 0/imm32
  514     c7 0/subop/copy *_Program-functions->payload 0/imm32
  515     c7 0/subop/copy *_Program-types 0/imm32
  516     c7 0/subop/copy *_Program-types->payload 0/imm32
  517     c7 0/subop/copy *_Program-signatures 0/imm32
  518     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  519     #
  520     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  521     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  522 #?     (dump-typeinfos "=== typeinfos\n")
  523     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  524     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  525 $convert-mu:end:
  526     # . restore registers
  527     58/pop-to-eax
  528     # . epilogue
  529     89/<- %esp 5/r32/ebp
  530     5d/pop-to-ebp
  531     c3/return
  532 
  533 test-convert-empty-input:
  534     # empty input => empty output
  535     # . prologue
  536     55/push-ebp
  537     89/<- %ebp 4/r32/esp
  538     # setup
  539     (clear-stream _test-input-stream)
  540     (clear-stream $_test-input-buffered-file->buffer)
  541     (clear-stream _test-output-stream)
  542     (clear-stream $_test-output-buffered-file->buffer)
  543     #
  544     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  545     (flush _test-output-buffered-file)
  546     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  547     # . epilogue
  548     89/<- %esp 5/r32/ebp
  549     5d/pop-to-ebp
  550     c3/return
  551 
  552 test-convert-function-skeleton:
  553     # . prologue
  554     55/push-ebp
  555     89/<- %ebp 4/r32/esp
  556     # setup
  557     (clear-stream _test-input-stream)
  558     (clear-stream $_test-input-buffered-file->buffer)
  559     (clear-stream _test-output-stream)
  560     (clear-stream $_test-output-buffered-file->buffer)
  561     #
  562     (write _test-input-stream "fn foo {\n")
  563     (write _test-input-stream "}\n")
  564     # convert
  565     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  566     (flush _test-output-buffered-file)
  567 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  573     # check output
  574     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  575     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  576     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  577     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  582     # . epilogue
  583     89/<- %esp 5/r32/ebp
  584     5d/pop-to-ebp
  585     c3/return
  586 
  587 test-convert-multiple-function-skeletons:
  588     # . prologue
  589     55/push-ebp
  590     89/<- %ebp 4/r32/esp
  591     # setup
  592     (clear-stream _test-input-stream)
  593     (clear-stream $_test-input-buffered-file->buffer)
  594     (clear-stream _test-output-stream)
  595     (clear-stream $_test-output-buffered-file->buffer)
  596     #
  597     (write _test-input-stream "fn foo {\n")
  598     (write _test-input-stream "}\n")
  599     (write _test-input-stream "fn bar {\n")
  600     (write _test-input-stream "}\n")
  601     # convert
  602     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  603     (flush _test-output-buffered-file)
  604 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  610     # check first function
  611     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  612     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  613     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  614     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  615     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  616     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  617     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  618     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  619     # check second function
  620     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  621     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  622     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  623     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  624     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  625     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  626     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  627     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  628     # . epilogue
  629     89/<- %esp 5/r32/ebp
  630     5d/pop-to-ebp
  631     c3/return
  632 
  633 test-convert-function-with-arg:
  634     # . prologue
  635     55/push-ebp
  636     89/<- %ebp 4/r32/esp
  637     # setup
  638     (clear-stream _test-input-stream)
  639     (clear-stream $_test-input-buffered-file->buffer)
  640     (clear-stream _test-output-stream)
  641     (clear-stream $_test-output-buffered-file->buffer)
  642     #
  643     (write _test-input-stream "fn foo n: int {\n")
  644     (write _test-input-stream "}\n")
  645     # convert
  646     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  647     (flush _test-output-buffered-file)
  648 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  654     # check output
  655     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  656     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  657     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  658     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  659     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  660     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  661     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  662     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  663     # . epilogue
  664     89/<- %esp 5/r32/ebp
  665     5d/pop-to-ebp
  666     c3/return
  667 
  668 test-convert-function-with-arg-and-body:
  669     # . prologue
  670     55/push-ebp
  671     89/<- %ebp 4/r32/esp
  672     # setup
  673     (clear-stream _test-input-stream)
  674     (clear-stream $_test-input-buffered-file->buffer)
  675     (clear-stream _test-output-stream)
  676     (clear-stream $_test-output-buffered-file->buffer)
  677     #
  678     (write _test-input-stream "fn foo n: int {\n")
  679     (write _test-input-stream "  increment n\n")
  680     (write _test-input-stream "}\n")
  681     # convert
  682     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  683     (flush _test-output-buffered-file)
  684 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  690     # check output
  691     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
  692     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
  693     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
  694     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
  695     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
  696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
  697     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
  698     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
  699     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
  700     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
  701     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
  702     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
  703     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
  704     # . epilogue
  705     89/<- %esp 5/r32/ebp
  706     5d/pop-to-ebp
  707     c3/return
  708 
  709 test-convert-function-distinguishes-args:
  710     # . prologue
  711     55/push-ebp
  712     89/<- %ebp 4/r32/esp
  713     # setup
  714     (clear-stream _test-input-stream)
  715     (clear-stream $_test-input-buffered-file->buffer)
  716     (clear-stream _test-output-stream)
  717     (clear-stream $_test-output-buffered-file->buffer)
  718     #
  719     (write _test-input-stream "fn foo a: int, b: int {\n")
  720     (write _test-input-stream "  increment b\n")
  721     (write _test-input-stream "}\n")
  722     # convert
  723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  724     (flush _test-output-buffered-file)
  725 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  731     # check output
  732     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
  733     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
  734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
  735     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
  736     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
  737     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
  738     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
  739     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
  740     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
  741     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
  742     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
  743     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
  744     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
  745     # . epilogue
  746     89/<- %esp 5/r32/ebp
  747     5d/pop-to-ebp
  748     c3/return
  749 
  750 test-convert-function-returns-result:
  751     # . prologue
  752     55/push-ebp
  753     89/<- %ebp 4/r32/esp
  754     # setup
  755     (clear-stream _test-input-stream)
  756     (clear-stream $_test-input-buffered-file->buffer)
  757     (clear-stream _test-output-stream)
  758     (clear-stream $_test-output-buffered-file->buffer)
  759     #
  760     (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n")
  761     (write _test-input-stream "  result <- copy a\n")
  762     (write _test-input-stream "  result <- increment\n")
  763     (write _test-input-stream "}\n")
  764     # convert
  765     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  766     (flush _test-output-buffered-file)
  767 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  773     # check output
  774     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-returns-result/0")
  775     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-returns-result/1")
  776     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-returns-result/2")
  777     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-returns-result/3")
  778     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-returns-result/4")
  779     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-returns-result/5")
  780     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-returns-result/6")
  781     (check-next-stream-line-equal _test-output-stream "    40/increment-eax"    "F - test-convert-function-returns-result/7")
  782     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-returns-result/8")
  783     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-returns-result/9")
  784     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-returns-result/10")
  785     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-returns-result/11")
  786     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-returns-result/12")
  787     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-returns-result/13")
  788     # . epilogue
  789     89/<- %esp 5/r32/ebp
  790     5d/pop-to-ebp
  791     c3/return
  792 
  793 test-convert-function-with-literal-arg:
  794     # . prologue
  795     55/push-ebp
  796     89/<- %ebp 4/r32/esp
  797     # setup
  798     (clear-stream _test-input-stream)
  799     (clear-stream $_test-input-buffered-file->buffer)
  800     (clear-stream _test-output-stream)
  801     (clear-stream $_test-output-buffered-file->buffer)
  802     #
  803     (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n")
  804     (write _test-input-stream "  result <- copy a\n")
  805     (write _test-input-stream "  result <- add 1\n")
  806     (write _test-input-stream "}\n")
  807     # convert
  808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  809     (flush _test-output-buffered-file)
  810 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  816     # check output
  817     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
  818     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
  819     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
  820     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
  821     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
  822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
  823     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/6")
  824     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/7")
  825     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/8")
  826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/9")
  827     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/10")
  828     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/11")
  829     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/12")
  830     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/13")
  831     # . epilogue
  832     89/<- %esp 5/r32/ebp
  833     5d/pop-to-ebp
  834     c3/return
  835 
  836 test-convert-function-with-literal-arg-2:
  837     # . prologue
  838     55/push-ebp
  839     89/<- %ebp 4/r32/esp
  840     # setup
  841     (clear-stream _test-input-stream)
  842     (clear-stream $_test-input-buffered-file->buffer)
  843     (clear-stream _test-output-stream)
  844     (clear-stream $_test-output-buffered-file->buffer)
  845     #
  846     (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n")
  847     (write _test-input-stream "  result <- copy a\n")
  848     (write _test-input-stream "  result <- add 1\n")
  849     (write _test-input-stream "}\n")
  850     # convert
  851     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  852     (flush _test-output-buffered-file)
  853 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  859     # check output
  860     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
  861     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
  862     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
  863     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
  864     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
  865     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
  866     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/6")
  867     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/7")
  868     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/8")
  869     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/9")
  870     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/10")
  871     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/11")
  872     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/12")
  873     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/13")
  874     # . epilogue
  875     89/<- %esp 5/r32/ebp
  876     5d/pop-to-ebp
  877     c3/return
  878 
  879 test-convert-function-call-with-literal-arg:
  880     # . prologue
  881     55/push-ebp
  882     89/<- %ebp 4/r32/esp
  883     # setup
  884     (clear-stream _test-input-stream)
  885     (clear-stream $_test-input-buffered-file->buffer)
  886     (clear-stream _test-output-stream)
  887     (clear-stream $_test-output-buffered-file->buffer)
  888     #
  889     (write _test-input-stream "fn main -> result/ebx: int {\n")
  890     (write _test-input-stream "  result <- do-add 3 4\n")
  891     (write _test-input-stream "}\n")
  892     (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n")
  893     (write _test-input-stream "  result <- copy a\n")
  894     (write _test-input-stream "  result <- add b\n")
  895     (write _test-input-stream "}\n")
  896     # convert
  897     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  898     (flush _test-output-buffered-file)
  899 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  905     # check output
  906     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
  907     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
  908     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
  909     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
  910     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
  911     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
  912     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/6")
  913     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/7")
  914     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8")
  915     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/9")
  916     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/10")
  917     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/11")
  918     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/12")
  919     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/13")
  920     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/14")
  921     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/15")
  922     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/16")
  923     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/17")
  924     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/18")
  925     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-call-with-literal-arg/19")
  926     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000003/r32"  "F - test-convert-function-call-with-literal-arg/20")
  927     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/21")
  928     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/22")
  929     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/23")
  930     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/24")
  931     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/25")
  932     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/26")
  933     # . epilogue
  934     89/<- %esp 5/r32/ebp
  935     5d/pop-to-ebp
  936     c3/return
  937 
  938 test-convert-function-call-with-signature:
  939     # . prologue
  940     55/push-ebp
  941     89/<- %ebp 4/r32/esp
  942     # setup
  943     (clear-stream _test-input-stream)
  944     (clear-stream $_test-input-buffered-file->buffer)
  945     (clear-stream _test-output-stream)
  946     (clear-stream $_test-output-buffered-file->buffer)
  947     #
  948     (write _test-input-stream "fn main -> result/ebx: int {\n")
  949     (write _test-input-stream "  result <- do-add 3 4\n")
  950     (write _test-input-stream "}\n")
  951     (write _test-input-stream "sig do-add a: int, b: int -> result/ebx: int\n")
  952     # convert
  953     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  954     (flush _test-output-buffered-file)
  955 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
  961     # check output
  962     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
  963     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
  964     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
  965     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
  966     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
  967     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
  968     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
  969     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
  970     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
  971     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
  972     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
  973     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
  974     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
  975     # . epilogue
  976     89/<- %esp 5/r32/ebp
  977     5d/pop-to-ebp
  978     c3/return
  979 
  980 test-convert-function-with-local-var-in-mem:
  981     # . prologue
  982     55/push-ebp
  983     89/<- %ebp 4/r32/esp
  984     # setup
  985     (clear-stream _test-input-stream)
  986     (clear-stream $_test-input-buffered-file->buffer)
  987     (clear-stream _test-output-stream)
  988     (clear-stream $_test-output-buffered-file->buffer)
  989     #
  990     (write _test-input-stream "fn foo {\n")
  991     (write _test-input-stream "  var x: int\n")
  992     (write _test-input-stream "  increment x\n")
  993     (write _test-input-stream "}\n")
  994     # convert
  995     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  996     (flush _test-output-buffered-file)
  997 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1003     # check output
 1004     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 1005     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 1006     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 1007     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 1008     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 1009     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 1010     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 1011     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 1012     (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")
 1013     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 1014     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 1015     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 1016     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 1017     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 1018     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 1019     # . epilogue
 1020     89/<- %esp 5/r32/ebp
 1021     5d/pop-to-ebp
 1022     c3/return
 1023 
 1024 test-convert-invalid-literal:
 1025     # . prologue
 1026     55/push-ebp
 1027     89/<- %ebp 4/r32/esp
 1028     # setup
 1029     (clear-stream _test-input-stream)
 1030     (clear-stream $_test-input-buffered-file->buffer)
 1031     (clear-stream _test-output-stream)
 1032     (clear-stream $_test-output-buffered-file->buffer)
 1033     (clear-stream _test-error-stream)
 1034     (clear-stream $_test-error-buffered-file->buffer)
 1035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1036     68/push 0/imm32
 1037     68/push 0/imm32
 1038     89/<- %edx 4/r32/esp
 1039     (tailor-exit-descriptor %edx 0x10)
 1040     #
 1041     (write _test-input-stream "fn foo {\n")
 1042     (write _test-input-stream "  increment 1n\n")
 1043     (write _test-input-stream "}\n")
 1044     # convert
 1045     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1046     # registers except esp clobbered at this point
 1047     # restore ed
 1048     89/<- %edx 4/r32/esp
 1049     (flush _test-output-buffered-file)
 1050     (flush _test-error-buffered-file)
 1051 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1057     # check output
 1058     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 1059     (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")
 1060     # check that stop(1) was called
 1061     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 1062     # don't restore from ebp
 1063     81 0/subop/add %esp 8/imm32
 1064     # . epilogue
 1065     5d/pop-to-ebp
 1066     c3/return
 1067 
 1068 test-local-var-in-mem-has-no-initializer:
 1069     # . prologue
 1070     55/push-ebp
 1071     89/<- %ebp 4/r32/esp
 1072     # setup
 1073     (clear-stream _test-input-stream)
 1074     (clear-stream $_test-input-buffered-file->buffer)
 1075     (clear-stream _test-output-stream)
 1076     (clear-stream $_test-output-buffered-file->buffer)
 1077     (clear-stream _test-error-stream)
 1078     (clear-stream $_test-error-buffered-file->buffer)
 1079     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1080     68/push 0/imm32
 1081     68/push 0/imm32
 1082     89/<- %edx 4/r32/esp
 1083     (tailor-exit-descriptor %edx 0x10)
 1084     #
 1085     (write _test-input-stream "fn foo {\n")
 1086     (write _test-input-stream "  var x: int <- copy 0\n")
 1087     (write _test-input-stream "  increment x\n")
 1088     (write _test-input-stream "}\n")
 1089     # convert
 1090     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1091     # registers except esp clobbered at this point
 1092     # restore ed
 1093     89/<- %edx 4/r32/esp
 1094     (flush _test-output-buffered-file)
 1095     (flush _test-error-buffered-file)
 1096 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1102     # check output
 1103     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 1104     (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")
 1105     # check that stop(1) was called
 1106     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 1107     # don't restore from ebp
 1108     81 0/subop/add %esp 8/imm32
 1109     # . epilogue
 1110     5d/pop-to-ebp
 1111     c3/return
 1112 
 1113 test-convert-function-with-local-var-with-compound-type-in-mem:
 1114     # . prologue
 1115     55/push-ebp
 1116     89/<- %ebp 4/r32/esp
 1117     # setup
 1118     (clear-stream _test-input-stream)
 1119     (clear-stream $_test-input-buffered-file->buffer)
 1120     (clear-stream _test-output-stream)
 1121     (clear-stream $_test-output-buffered-file->buffer)
 1122     #
 1123     (write _test-input-stream "fn foo {\n")
 1124     (write _test-input-stream "  var x: (addr int)\n")
 1125     (write _test-input-stream "  copy-to x, 0\n")
 1126     (write _test-input-stream "}\n")
 1127     # convert
 1128     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1129     (flush _test-output-buffered-file)
 1130 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1136     # check output
 1137     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 1138     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 1139     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 1140     (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")
 1141     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 1142     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 1143     (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")
 1144     (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")
 1145     (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")
 1146     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 1147     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 1148     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 1149     (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")
 1150     (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")
 1151     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 1152     # . epilogue
 1153     89/<- %esp 5/r32/ebp
 1154     5d/pop-to-ebp
 1155     c3/return
 1156 
 1157 test-convert-function-with-local-var-in-reg:
 1158     # . prologue
 1159     55/push-ebp
 1160     89/<- %ebp 4/r32/esp
 1161     # setup
 1162     (clear-stream _test-input-stream)
 1163     (clear-stream $_test-input-buffered-file->buffer)
 1164     (clear-stream _test-output-stream)
 1165     (clear-stream $_test-output-buffered-file->buffer)
 1166     #
 1167     (write _test-input-stream "fn foo {\n")
 1168     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1169     (write _test-input-stream "  x <- increment\n")
 1170     (write _test-input-stream "}\n")
 1171     # convert
 1172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1173     (flush _test-output-buffered-file)
 1174 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1180     # check output
 1181     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 1182     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 1183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 1184     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 1185     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 1186     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 1187     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 1188     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 1189     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 1190     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 1191     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 1192     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 1193     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 1194     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 1195     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 1196     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 1197     # . epilogue
 1198     89/<- %esp 5/r32/ebp
 1199     5d/pop-to-ebp
 1200     c3/return
 1201 
 1202 test-convert-function-with-allocate:
 1203     # . prologue
 1204     55/push-ebp
 1205     89/<- %ebp 4/r32/esp
 1206     # setup
 1207     (clear-stream _test-input-stream)
 1208     (clear-stream $_test-input-buffered-file->buffer)
 1209     (clear-stream _test-output-stream)
 1210     (clear-stream $_test-output-buffered-file->buffer)
 1211     #
 1212     (write _test-input-stream "fn foo {\n")
 1213     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 1214     (write _test-input-stream "  allocate x\n")
 1215     (write _test-input-stream "}\n")
 1216     # convert
 1217     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1218     (flush _test-output-buffered-file)
 1219 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1225     # check output
 1226     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 1227     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 1228     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 1229     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 1230     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 1231     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 1232     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 1233     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 1234     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 1235     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 1236     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 1237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 1238     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 1239     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 1240     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 1241     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 1242     # . epilogue
 1243     89/<- %esp 5/r32/ebp
 1244     5d/pop-to-ebp
 1245     c3/return
 1246 
 1247 test-initializer-in-hex:
 1248     # . prologue
 1249     55/push-ebp
 1250     89/<- %ebp 4/r32/esp
 1251     # setup
 1252     (clear-stream _test-input-stream)
 1253     (clear-stream $_test-input-buffered-file->buffer)
 1254     (clear-stream _test-output-stream)
 1255     (clear-stream $_test-output-buffered-file->buffer)
 1256     (clear-stream _test-error-stream)
 1257     (clear-stream $_test-error-buffered-file->buffer)
 1258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1259     68/push 0/imm32
 1260     68/push 0/imm32
 1261     89/<- %edx 4/r32/esp
 1262     (tailor-exit-descriptor %edx 0x10)
 1263     #
 1264     (write _test-input-stream "fn foo {\n")
 1265     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 1266     (write _test-input-stream "}\n")
 1267     # convert
 1268     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1269     # registers except esp clobbered at this point
 1270     # restore ed
 1271     89/<- %edx 4/r32/esp
 1272     (flush _test-output-buffered-file)
 1273     (flush _test-error-buffered-file)
 1274 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1280     # check output
 1281     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 1282     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; either start '10' with a '0x' to be unambiguous, or convert it to decimal."  "F - test-initializer-in-hex: error message")
 1283     # check that stop(1) was called
 1284     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 1285     # don't restore from ebp
 1286     81 0/subop/add %esp 8/imm32
 1287     # . epilogue
 1288     5d/pop-to-ebp
 1289     c3/return
 1290 
 1291 test-convert-function-with-second-local-var-in-same-reg:
 1292     # . prologue
 1293     55/push-ebp
 1294     89/<- %ebp 4/r32/esp
 1295     # setup
 1296     (clear-stream _test-input-stream)
 1297     (clear-stream $_test-input-buffered-file->buffer)
 1298     (clear-stream _test-output-stream)
 1299     (clear-stream $_test-output-buffered-file->buffer)
 1300     #
 1301     (write _test-input-stream "fn foo {\n")
 1302     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1303     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1304     (write _test-input-stream "  y <- increment\n")
 1305     (write _test-input-stream "}\n")
 1306     # convert
 1307     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1308     (flush _test-output-buffered-file)
 1309 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1315     # check output
 1316     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 1317     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 1318     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 1319     (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")
 1320     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 1321     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 1322     (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")
 1323     (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")
 1324     (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")
 1325     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 1326     (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")
 1327     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 1328     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 1329     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 1330     (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")
 1331     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 1332     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 1333     # . epilogue
 1334     89/<- %esp 5/r32/ebp
 1335     5d/pop-to-ebp
 1336     c3/return
 1337 
 1338 test-read-clobbered-reg-var:
 1339     # . prologue
 1340     55/push-ebp
 1341     89/<- %ebp 4/r32/esp
 1342     # setup
 1343     (clear-stream _test-input-stream)
 1344     (clear-stream $_test-input-buffered-file->buffer)
 1345     (clear-stream _test-output-stream)
 1346     (clear-stream $_test-output-buffered-file->buffer)
 1347     (clear-stream _test-error-stream)
 1348     (clear-stream $_test-error-buffered-file->buffer)
 1349     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 1350     68/push 0/imm32
 1351     68/push 0/imm32
 1352     89/<- %edx 4/r32/esp
 1353     (tailor-exit-descriptor %edx 0x10)
 1354     #
 1355     (write _test-input-stream "fn foo {\n")
 1356     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 1357     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 1358     (write _test-input-stream "  x <- increment\n")
 1359     (write _test-input-stream "}\n")
 1360     # convert
 1361     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1362     # registers except esp clobbered at this point
 1363     # restore ed
 1364     89/<- %edx 4/r32/esp
 1365     (flush _test-output-buffered-file)
 1366     (flush _test-error-buffered-file)
 1367 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1373     # check output
 1374     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 1375     (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")
 1376     # check that stop(1) was called
 1377     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 1378     # don't restore from ebp
 1379     81 0/subop/add %esp 8/imm32
 1380     # . epilogue
 1381     5d/pop-to-ebp
 1382     c3/return
 1383 
 1384 test-overlapping-int-fp-registers:
 1385     # . prologue
 1386     55/push-ebp
 1387     89/<- %ebp 4/r32/esp
 1388     # setup
 1389     (clear-stream _test-input-stream)
 1390     (clear-stream $_test-input-buffered-file->buffer)
 1391     (clear-stream _test-output-stream)
 1392     (clear-stream $_test-output-buffered-file->buffer)
 1393     (clear-stream _test-error-stream)
 1394     (clear-stream $_test-error-buffered-file->buffer)
 1395     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 1396     68/push 0/imm32
 1397     68/push 0/imm32
 1398     89/<- %edx 4/r32/esp
 1399     (tailor-exit-descriptor %edx 0x10)
 1400     #
 1401     (write _test-input-stream "fn foo {\n")
 1402     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 1403     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 1404     (write _test-input-stream "  x <- increment\n")
 1405     (write _test-input-stream "}\n")
 1406     # convert
 1407     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1408     # registers except esp clobbered at this point
 1409     # restore ed
 1410     89/<- %edx 4/r32/esp
 1411     (flush _test-output-buffered-file)
 1412     (flush _test-error-buffered-file)
 1413 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1419     # no errors
 1420     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 1421     # don't bother checking the generated code
 1422     # don't restore from ebp
 1423     81 0/subop/add %esp 8/imm32
 1424     # . epilogue
 1425     5d/pop-to-ebp
 1426     c3/return
 1427 
 1428 test-convert-function-call:
 1429     # . prologue
 1430     55/push-ebp
 1431     89/<- %ebp 4/r32/esp
 1432     # setup
 1433     (clear-stream _test-input-stream)
 1434     (clear-stream $_test-input-buffered-file->buffer)
 1435     (clear-stream _test-output-stream)
 1436     (clear-stream $_test-output-buffered-file->buffer)
 1437     #
 1438     (write _test-input-stream "fn main -> result/ebx: int {\n")
 1439     (write _test-input-stream "  result <- foo\n")
 1440     (write _test-input-stream "}\n")
 1441     (write _test-input-stream "fn foo -> result/ebx: int {\n")
 1442     (write _test-input-stream "  result <- copy 3\n")
 1443     (write _test-input-stream "}\n")
 1444     # convert
 1445     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1446     (flush _test-output-buffered-file)
 1447 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1453     # check output
 1454     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 1455     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 1456     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 1457     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 1458     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 1459     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 1460     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 1461     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 1462     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 1463     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 1464     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 1465     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 1466     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 1467     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 1468     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 1469     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 1470     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 1471     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 1472     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 1473     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 1474     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 1475     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 1476     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 1477     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 1478     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 1479     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 1480     # . epilogue
 1481     89/<- %esp 5/r32/ebp
 1482     5d/pop-to-ebp
 1483     c3/return
 1484 
 1485 test-convert-function-call-with-inout-with-compound-type:
 1486     # . prologue
 1487     55/push-ebp
 1488     89/<- %ebp 4/r32/esp
 1489     # setup
 1490     (clear-stream _test-input-stream)
 1491     (clear-stream $_test-input-buffered-file->buffer)
 1492     (clear-stream _test-output-stream)
 1493     (clear-stream $_test-output-buffered-file->buffer)
 1494     #
 1495     (write _test-input-stream "fn f {\n")
 1496     (write _test-input-stream "  var x: (addr int)\n")
 1497     (write _test-input-stream "  g x\n")
 1498     (write _test-input-stream "}\n")
 1499     (write _test-input-stream "fn g a: (addr int) {\n")
 1500     (write _test-input-stream "}\n")
 1501     # convert
 1502     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1503     (flush _test-output-buffered-file)
 1504 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 1510     # check output
 1511     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 1512     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 1513     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 1514     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 1515     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 1516     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 1517     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 1518     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 1519     (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")
 1520     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 1521     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 1522     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 1523     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 1524     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 1525     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 1526     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 1527     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 1528     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 1529     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 1530     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 1531     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 1532     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 1533     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 1534     # . epilogue
 1535     89/<- %esp 5/r32/ebp
 1536     5d/pop-to-ebp
 1537     c3/return
 1538 
 1539 test-convert-function-call-with-inout-with-type-parameter:
 1540     # . prologue
 1541     55/push-ebp
 1542     89/<- %ebp 4/r32/esp
 1543     # setup
 1544     (clear-stream _test-input-stream)
 1545     (clear-stream $_test-input-buffered-file->buffer)
 1546     (clear-stream _test-output-stream)
 1547     (clear-stream $_test-output-buffered-file->buffer)
 1548     (clear-stream _test-error-stream)
 1549     (clear-stream $_test-error-buffered-file->buffer)
 1550     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1551     68/push 0/imm32
 1552     68/push 0/imm32
 1553     89/<- %edx 4/r32/esp
 1554     (tailor-exit-descriptor %edx 0x10)
 1555     #
 1556     (write _test-input-stream "fn f {\n")
 1557     (write _test-input-stream "  var x: (addr int)\n")
 1558     (write _test-input-stream "  g x\n")
 1559     (write _test-input-stream "}\n")
 1560     (write _test-input-stream "fn g a: (addr _) {\n")
 1561     (write _test-input-stream "}\n")
 1562     # convert
 1563     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1564     # registers except esp clobbered at this point
 1565     # restore ed
 1566     89/<- %edx 4/r32/esp
 1567     (flush _test-output-buffered-file)
 1568     (flush _test-error-buffered-file)
 1569 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1575     # no error; types matched
 1576     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 1577     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 1578     # don't restore from ebp
 1579     81 0/subop/add %esp 8/imm32
 1580     # . epilogue
 1581     5d/pop-to-ebp
 1582     c3/return
 1583 
 1584 test-convert-function-call-with-incorrect-inout-type:
 1585     # . prologue
 1586     55/push-ebp
 1587     89/<- %ebp 4/r32/esp
 1588     # setup
 1589     (clear-stream _test-input-stream)
 1590     (clear-stream $_test-input-buffered-file->buffer)
 1591     (clear-stream _test-output-stream)
 1592     (clear-stream $_test-output-buffered-file->buffer)
 1593     (clear-stream _test-error-stream)
 1594     (clear-stream $_test-error-buffered-file->buffer)
 1595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1596     68/push 0/imm32
 1597     68/push 0/imm32
 1598     89/<- %edx 4/r32/esp
 1599     (tailor-exit-descriptor %edx 0x10)
 1600     #
 1601     (write _test-input-stream "fn f {\n")
 1602     (write _test-input-stream "  var x: int\n")
 1603     (write _test-input-stream "  g x\n")
 1604     (write _test-input-stream "}\n")
 1605     (write _test-input-stream "fn g a: foo {\n")
 1606     (write _test-input-stream "}\n")
 1607     # convert
 1608     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1609     # registers except esp clobbered at this point
 1610     # restore ed
 1611     89/<- %edx 4/r32/esp
 1612     (flush _test-output-buffered-file)
 1613     (flush _test-error-buffered-file)
 1614 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1620     # check output
 1621     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 1622     (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")
 1623     # check that stop(1) was called
 1624     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 1625     # don't restore from ebp
 1626     81 0/subop/add %esp 8/imm32
 1627     5d/pop-to-ebp
 1628     c3/return
 1629 
 1630 test-convert-function-call-with-inout-with-incorrect-compound-type:
 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 f {\n")
 1648     (write _test-input-stream "  var x: (addr int)\n")
 1649     (write _test-input-stream "  g x\n")
 1650     (write _test-input-stream "}\n")
 1651     (write _test-input-stream "fn g a: (addr bool) {\n")
 1652     (write _test-input-stream "}\n")
 1653     # convert
 1654     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1655     # registers except esp clobbered at this point
 1656     # restore ed
 1657     89/<- %edx 4/r32/esp
 1658     (flush _test-output-buffered-file)
 1659     (flush _test-error-buffered-file)
 1660 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1666     # check output
 1667     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 1668     (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")
 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-convert-function-call-with-inout-with-multiple-type-parameters:
 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 f {\n")
 1693     (write _test-input-stream "  var x: (addr int)\n")
 1694     (write _test-input-stream "  var y: (addr int)\n")
 1695     (write _test-input-stream "  g x, y\n")
 1696     (write _test-input-stream "}\n")
 1697     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 1698     (write _test-input-stream "}\n")
 1699     # convert
 1700     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1701     # registers except esp clobbered at this point
 1702     # restore ed
 1703     89/<- %edx 4/r32/esp
 1704     (flush _test-output-buffered-file)
 1705     (flush _test-error-buffered-file)
 1706 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1712     # no errors
 1713     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 1714     # don't bother checking the generated code
 1715     # don't restore from ebp
 1716     81 0/subop/add %esp 8/imm32
 1717     # . epilogue
 1718     5d/pop-to-ebp
 1719     c3/return
 1720 
 1721 test-type-parameter-matches-rest-of-type:
 1722     # . prologue
 1723     55/push-ebp
 1724     89/<- %ebp 4/r32/esp
 1725     # setup
 1726     (clear-stream _test-input-stream)
 1727     (clear-stream $_test-input-buffered-file->buffer)
 1728     (clear-stream _test-output-stream)
 1729     (clear-stream $_test-output-buffered-file->buffer)
 1730     (clear-stream _test-error-stream)
 1731     (clear-stream $_test-error-buffered-file->buffer)
 1732     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1733     68/push 0/imm32
 1734     68/push 0/imm32
 1735     89/<- %edx 4/r32/esp
 1736     (tailor-exit-descriptor %edx 0x10)
 1737     #
 1738     (write _test-input-stream "fn f {\n")
 1739     (write _test-input-stream "  var x: (addr array int)\n")
 1740     (write _test-input-stream "  g x\n")
 1741     (write _test-input-stream "}\n")
 1742     (write _test-input-stream "fn g a: (addr _) {\n")
 1743     (write _test-input-stream "}\n")
 1744     # convert
 1745     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1746     # registers except esp clobbered at this point
 1747     # restore ed
 1748     89/<- %edx 4/r32/esp
 1749     (flush _test-output-buffered-file)
 1750     (flush _test-error-buffered-file)
 1751 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1757     # no errors
 1758     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 1759     # don't bother checking the generated code
 1760     # don't restore from ebp
 1761     81 0/subop/add %esp 8/imm32
 1762     # . epilogue
 1763     5d/pop-to-ebp
 1764     c3/return
 1765 
 1766 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 1767     # . prologue
 1768     55/push-ebp
 1769     89/<- %ebp 4/r32/esp
 1770     # setup
 1771     (clear-stream _test-input-stream)
 1772     (clear-stream $_test-input-buffered-file->buffer)
 1773     (clear-stream _test-output-stream)
 1774     (clear-stream $_test-output-buffered-file->buffer)
 1775     (clear-stream _test-error-stream)
 1776     (clear-stream $_test-error-buffered-file->buffer)
 1777     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1778     68/push 0/imm32
 1779     68/push 0/imm32
 1780     89/<- %edx 4/r32/esp
 1781     (tailor-exit-descriptor %edx 0x10)
 1782     #
 1783     (write _test-input-stream "fn f {\n")
 1784     (write _test-input-stream "  var x: (addr int)\n")
 1785     (write _test-input-stream "  var y: (addr boolean)\n")
 1786     (write _test-input-stream "  g x, y\n")
 1787     (write _test-input-stream "}\n")
 1788     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 1789     (write _test-input-stream "}\n")
 1790     # convert
 1791     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1792     # registers except esp clobbered at this point
 1793     # restore ed
 1794     89/<- %edx 4/r32/esp
 1795     (flush _test-output-buffered-file)
 1796     (flush _test-error-buffered-file)
 1797 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1803     # check output
 1804     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 1805     (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")
 1806     # don't restore from ebp
 1807     81 0/subop/add %esp 8/imm32
 1808     # . epilogue
 1809     5d/pop-to-ebp
 1810     c3/return
 1811 
 1812 test-convert-function-call-with-too-few-inouts:
 1813     # . prologue
 1814     55/push-ebp
 1815     89/<- %ebp 4/r32/esp
 1816     # setup
 1817     (clear-stream _test-input-stream)
 1818     (clear-stream $_test-input-buffered-file->buffer)
 1819     (clear-stream _test-output-stream)
 1820     (clear-stream $_test-output-buffered-file->buffer)
 1821     (clear-stream _test-error-stream)
 1822     (clear-stream $_test-error-buffered-file->buffer)
 1823     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1824     68/push 0/imm32
 1825     68/push 0/imm32
 1826     89/<- %edx 4/r32/esp
 1827     (tailor-exit-descriptor %edx 0x10)
 1828     #
 1829     (write _test-input-stream "fn f {\n")
 1830     (write _test-input-stream "  g\n")
 1831     (write _test-input-stream "}\n")
 1832     (write _test-input-stream "fn g a: int {\n")
 1833     (write _test-input-stream "}\n")
 1834     # convert
 1835     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1836     # registers except esp clobbered at this point
 1837     # restore ed
 1838     89/<- %edx 4/r32/esp
 1839     (flush _test-output-buffered-file)
 1840     (flush _test-error-buffered-file)
 1841 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1847     # check output
 1848     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 1849     (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")
 1850     # check that stop(1) was called
 1851     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 1852     # don't restore from ebp
 1853     81 0/subop/add %esp 8/imm32
 1854     5d/pop-to-ebp
 1855     c3/return
 1856 
 1857 test-convert-function-call-with-too-many-inouts:
 1858     # . prologue
 1859     55/push-ebp
 1860     89/<- %ebp 4/r32/esp
 1861     # setup
 1862     (clear-stream _test-input-stream)
 1863     (clear-stream $_test-input-buffered-file->buffer)
 1864     (clear-stream _test-output-stream)
 1865     (clear-stream $_test-output-buffered-file->buffer)
 1866     (clear-stream _test-error-stream)
 1867     (clear-stream $_test-error-buffered-file->buffer)
 1868     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1869     68/push 0/imm32
 1870     68/push 0/imm32
 1871     89/<- %edx 4/r32/esp
 1872     (tailor-exit-descriptor %edx 0x10)
 1873     #
 1874     (write _test-input-stream "fn f {\n")
 1875     (write _test-input-stream "  var x: int\n")
 1876     (write _test-input-stream "  g x\n")
 1877     (write _test-input-stream "}\n")
 1878     (write _test-input-stream "fn g {\n")
 1879     (write _test-input-stream "}\n")
 1880     # convert
 1881     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1882     # registers except esp clobbered at this point
 1883     # restore ed
 1884     89/<- %edx 4/r32/esp
 1885     (flush _test-output-buffered-file)
 1886     (flush _test-error-buffered-file)
 1887 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1893     # check output
 1894     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 1895     (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")
 1896     # check that stop(1) was called
 1897     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 1898     # don't restore from ebp
 1899     81 0/subop/add %esp 8/imm32
 1900     5d/pop-to-ebp
 1901     c3/return
 1902 
 1903 test-convert-function-call-with-incorrect-output-type:
 1904     # . prologue
 1905     55/push-ebp
 1906     89/<- %ebp 4/r32/esp
 1907     # setup
 1908     (clear-stream _test-input-stream)
 1909     (clear-stream $_test-input-buffered-file->buffer)
 1910     (clear-stream _test-output-stream)
 1911     (clear-stream $_test-output-buffered-file->buffer)
 1912     (clear-stream _test-error-stream)
 1913     (clear-stream $_test-error-buffered-file->buffer)
 1914     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1915     68/push 0/imm32
 1916     68/push 0/imm32
 1917     89/<- %edx 4/r32/esp
 1918     (tailor-exit-descriptor %edx 0x10)
 1919     #
 1920     (write _test-input-stream "fn f {\n")
 1921     (write _test-input-stream "  var x/eax: int <- g\n")
 1922     (write _test-input-stream "}\n")
 1923     (write _test-input-stream "fn g -> a/eax: foo {\n")
 1924     (write _test-input-stream "}\n")
 1925     # convert
 1926     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1927     # registers except esp clobbered at this point
 1928     # restore ed
 1929     89/<- %edx 4/r32/esp
 1930     (flush _test-output-buffered-file)
 1931     (flush _test-error-buffered-file)
 1932 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1938     # check output
 1939     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 1940     (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")
 1941     # check that stop(1) was called
 1942     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 1943     # don't restore from ebp
 1944     81 0/subop/add %esp 8/imm32
 1945     5d/pop-to-ebp
 1946     c3/return
 1947 
 1948 test-convert-function-call-with-too-few-outputs:
 1949     # . prologue
 1950     55/push-ebp
 1951     89/<- %ebp 4/r32/esp
 1952     # setup
 1953     (clear-stream _test-input-stream)
 1954     (clear-stream $_test-input-buffered-file->buffer)
 1955     (clear-stream _test-output-stream)
 1956     (clear-stream $_test-output-buffered-file->buffer)
 1957     (clear-stream _test-error-stream)
 1958     (clear-stream $_test-error-buffered-file->buffer)
 1959     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1960     68/push 0/imm32
 1961     68/push 0/imm32
 1962     89/<- %edx 4/r32/esp
 1963     (tailor-exit-descriptor %edx 0x10)
 1964     #
 1965     (write _test-input-stream "fn f {\n")
 1966     (write _test-input-stream "  g\n")
 1967     (write _test-input-stream "}\n")
 1968     (write _test-input-stream "fn g -> a/eax: int {\n")
 1969     (write _test-input-stream "}\n")
 1970     # convert
 1971     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1972     # registers except esp clobbered at this point
 1973     # restore ed
 1974     89/<- %edx 4/r32/esp
 1975     (flush _test-output-buffered-file)
 1976     (flush _test-error-buffered-file)
 1977 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 1983     # check output
 1984     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 1985     (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")
 1986     # check that stop(1) was called
 1987     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 1988     # don't restore from ebp
 1989     81 0/subop/add %esp 8/imm32
 1990     5d/pop-to-ebp
 1991     c3/return
 1992 
 1993 test-convert-function-call-with-too-many-outputs:
 1994     # . prologue
 1995     55/push-ebp
 1996     89/<- %ebp 4/r32/esp
 1997     # setup
 1998     (clear-stream _test-input-stream)
 1999     (clear-stream $_test-input-buffered-file->buffer)
 2000     (clear-stream _test-output-stream)
 2001     (clear-stream $_test-output-buffered-file->buffer)
 2002     (clear-stream _test-error-stream)
 2003     (clear-stream $_test-error-buffered-file->buffer)
 2004     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2005     68/push 0/imm32
 2006     68/push 0/imm32
 2007     89/<- %edx 4/r32/esp
 2008     (tailor-exit-descriptor %edx 0x10)
 2009     #
 2010     (write _test-input-stream "fn f {\n")
 2011     (write _test-input-stream "  var x/eax: int <- g\n")
 2012     (write _test-input-stream "}\n")
 2013     (write _test-input-stream "fn g {\n")
 2014     (write _test-input-stream "}\n")
 2015     # convert
 2016     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2017     # registers except esp clobbered at this point
 2018     # restore ed
 2019     89/<- %edx 4/r32/esp
 2020     (flush _test-output-buffered-file)
 2021     (flush _test-error-buffered-file)
 2022 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2028     # check output
 2029     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 2030     (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")
 2031     # check that stop(1) was called
 2032     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 2033     # don't restore from ebp
 2034     81 0/subop/add %esp 8/imm32
 2035     5d/pop-to-ebp
 2036     c3/return
 2037 
 2038 test-convert-function-call-with-missing-output-register:
 2039     # . prologue
 2040     55/push-ebp
 2041     89/<- %ebp 4/r32/esp
 2042     # setup
 2043     (clear-stream _test-input-stream)
 2044     (clear-stream $_test-input-buffered-file->buffer)
 2045     (clear-stream _test-output-stream)
 2046     (clear-stream $_test-output-buffered-file->buffer)
 2047     (clear-stream _test-error-stream)
 2048     (clear-stream $_test-error-buffered-file->buffer)
 2049     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2050     68/push 0/imm32
 2051     68/push 0/imm32
 2052     89/<- %edx 4/r32/esp
 2053     (tailor-exit-descriptor %edx 0x10)
 2054     #
 2055     (write _test-input-stream "fn f {\n")
 2056     (write _test-input-stream "  var x: int\n")
 2057     (write _test-input-stream "  x <- g\n")
 2058     (write _test-input-stream "}\n")
 2059     (write _test-input-stream "fn g -> a/eax: int {\n")
 2060     (write _test-input-stream "}\n")
 2061     # convert
 2062     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2063     # registers except esp clobbered at this point
 2064     # restore ed
 2065     89/<- %edx 4/r32/esp
 2066     (flush _test-output-buffered-file)
 2067     (flush _test-error-buffered-file)
 2068 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2074     # check output
 2075     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 2076     (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")
 2077     # check that stop(1) was called
 2078     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 2079     # don't restore from ebp
 2080     81 0/subop/add %esp 8/imm32
 2081     5d/pop-to-ebp
 2082     c3/return
 2083 
 2084 test-convert-function-call-with-incorrect-output-register:
 2085     # . prologue
 2086     55/push-ebp
 2087     89/<- %ebp 4/r32/esp
 2088     # setup
 2089     (clear-stream _test-input-stream)
 2090     (clear-stream $_test-input-buffered-file->buffer)
 2091     (clear-stream _test-output-stream)
 2092     (clear-stream $_test-output-buffered-file->buffer)
 2093     (clear-stream _test-error-stream)
 2094     (clear-stream $_test-error-buffered-file->buffer)
 2095     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2096     68/push 0/imm32
 2097     68/push 0/imm32
 2098     89/<- %edx 4/r32/esp
 2099     (tailor-exit-descriptor %edx 0x10)
 2100     #
 2101     (write _test-input-stream "fn f {\n")
 2102     (write _test-input-stream "  var x/ecx: int <- g\n")
 2103     (write _test-input-stream "}\n")
 2104     (write _test-input-stream "fn g -> a/eax: int {\n")
 2105     (write _test-input-stream "}\n")
 2106     # convert
 2107     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2108     # registers except esp clobbered at this point
 2109     # restore ed
 2110     89/<- %edx 4/r32/esp
 2111     (flush _test-output-buffered-file)
 2112     (flush _test-error-buffered-file)
 2113 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2119     # check output
 2120     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 2121     (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")
 2122     # check that stop(1) was called
 2123     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 2124     # don't restore from ebp
 2125     81 0/subop/add %esp 8/imm32
 2126     5d/pop-to-ebp
 2127     c3/return
 2128 
 2129 test-convert-function-with-local-var-dereferenced:
 2130     # . prologue
 2131     55/push-ebp
 2132     89/<- %ebp 4/r32/esp
 2133     # setup
 2134     (clear-stream _test-input-stream)
 2135     (clear-stream $_test-input-buffered-file->buffer)
 2136     (clear-stream _test-output-stream)
 2137     (clear-stream $_test-output-buffered-file->buffer)
 2138     #
 2139     (write _test-input-stream "fn foo {\n")
 2140     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 2141     (write _test-input-stream "  increment *x\n")
 2142     (write _test-input-stream "}\n")
 2143     # convert
 2144     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2145     (flush _test-output-buffered-file)
 2146 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2152     # check output
 2153     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 2154     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 2155     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 2156     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 2157     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 2158     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 2159     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 2160     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 2161     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 2162     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 2163     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 2164     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 2165     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 2166     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 2167     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 2168     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 2169     # . epilogue
 2170     89/<- %esp 5/r32/ebp
 2171     5d/pop-to-ebp
 2172     c3/return
 2173 
 2174 # variables of type 'byte' are not allowed on the stack
 2175 test-convert-function-with-byte-operations:
 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 foo {\n")
 2186     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 2187     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 2188     (write _test-input-stream "  y <- copy-byte x\n")
 2189     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 2190     (write _test-input-stream "  y <- copy-byte *z\n")
 2191     (write _test-input-stream "  copy-byte-to *z, x\n")
 2192     (write _test-input-stream "}\n")
 2193     # convert
 2194     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2195     (flush _test-output-buffered-file)
 2196 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2202     # check output
 2203     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 2204     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 2205     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 2206     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 2207     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 2208     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 2209     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 2210     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 2211     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 2212     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 2213     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 2214     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 2215     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 2216     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 2217     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 2218     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 2219     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 2220     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 2221     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 2222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 2223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 2224     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 2225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 2226     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 2227     # . epilogue
 2228     89/<- %esp 5/r32/ebp
 2229     5d/pop-to-ebp
 2230     c3/return
 2231 
 2232 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 2233 test-copy-byte-var-from-fn-arg:
 2234     # . prologue
 2235     55/push-ebp
 2236     89/<- %ebp 4/r32/esp
 2237     # setup
 2238     (clear-stream _test-input-stream)
 2239     (clear-stream $_test-input-buffered-file->buffer)
 2240     (clear-stream _test-output-stream)
 2241     (clear-stream $_test-output-buffered-file->buffer)
 2242     #
 2243     (write _test-input-stream "fn foo x: byte, y: int {\n")
 2244     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 2245     (write _test-input-stream "  var b/eax: int <- copy y\n")
 2246     (write _test-input-stream "}\n")
 2247     # convert
 2248     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2249     (flush _test-output-buffered-file)
 2250 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2256     # check output
 2257     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 2258     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 2259     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 2260     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 2261     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 2262     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 2263     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 2264     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 2265     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 2266     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 2267     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 2268     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 2269     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 2270     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 2271     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 2272     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 2273     # . epilogue
 2274     89/<- %esp 5/r32/ebp
 2275     5d/pop-to-ebp
 2276     c3/return
 2277 
 2278 test-convert-compare-register-with-literal:
 2279     # . prologue
 2280     55/push-ebp
 2281     89/<- %ebp 4/r32/esp
 2282     # setup
 2283     (clear-stream _test-input-stream)
 2284     (clear-stream $_test-input-buffered-file->buffer)
 2285     (clear-stream _test-output-stream)
 2286     (clear-stream $_test-output-buffered-file->buffer)
 2287     #
 2288     (write _test-input-stream "fn foo {\n")
 2289     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 2290     (write _test-input-stream "  compare x, 0\n")
 2291     (write _test-input-stream "}\n")
 2292     # convert
 2293     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2294     (flush _test-output-buffered-file)
 2295 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2301     # check output
 2302     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 2303     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 2304     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 2305     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 2306     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 2307     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 2308     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2309     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 2310     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 2311     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2312     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 2313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 2314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 2315     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 2316     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 2317     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 2318     # . epilogue
 2319     89/<- %esp 5/r32/ebp
 2320     5d/pop-to-ebp
 2321     c3/return
 2322 
 2323 test-unknown-variable:
 2324     # . prologue
 2325     55/push-ebp
 2326     89/<- %ebp 4/r32/esp
 2327     # setup
 2328     (clear-stream _test-input-stream)
 2329     (clear-stream $_test-input-buffered-file->buffer)
 2330     (clear-stream _test-output-stream)
 2331     (clear-stream $_test-output-buffered-file->buffer)
 2332     (clear-stream _test-error-stream)
 2333     (clear-stream $_test-error-buffered-file->buffer)
 2334     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2335     68/push 0/imm32
 2336     68/push 0/imm32
 2337     89/<- %edx 4/r32/esp
 2338     (tailor-exit-descriptor %edx 0x10)
 2339     #
 2340     (write _test-input-stream "fn foo {\n")
 2341     (write _test-input-stream "  compare x, 0\n")
 2342     (write _test-input-stream "}\n")
 2343     # convert
 2344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2345     # registers except esp clobbered at this point
 2346     # restore ed
 2347     89/<- %edx 4/r32/esp
 2348     (flush _test-output-buffered-file)
 2349     (flush _test-error-buffered-file)
 2350 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2356     # check output
 2357     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 2358     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 2359     # check that stop(1) was called
 2360     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 2361     # don't restore from ebp
 2362     81 0/subop/add %esp 8/imm32
 2363     # . epilogue
 2364     5d/pop-to-ebp
 2365     c3/return
 2366 
 2367 test-convert-function-with-local-var-in-block:
 2368     # . prologue
 2369     55/push-ebp
 2370     89/<- %ebp 4/r32/esp
 2371     # setup
 2372     (clear-stream _test-input-stream)
 2373     (clear-stream $_test-input-buffered-file->buffer)
 2374     (clear-stream _test-output-stream)
 2375     (clear-stream $_test-output-buffered-file->buffer)
 2376     #
 2377     (write _test-input-stream "fn foo {\n")
 2378     (write _test-input-stream "  {\n")
 2379     (write _test-input-stream "    var x: int\n")
 2380     (write _test-input-stream "    increment x\n")
 2381     (write _test-input-stream "  }\n")
 2382     (write _test-input-stream "}\n")
 2383     # convert
 2384     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2385     (flush _test-output-buffered-file)
 2386 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2392     # check output
 2393     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 2394     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 2395     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 2396     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 2397     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 2398     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 2399     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 2400     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 2401     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 2402     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 2403     (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")
 2404     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 2405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 2406     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 2407     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 2408     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 2409     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 2410     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 2411     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 2412     # . epilogue
 2413     89/<- %esp 5/r32/ebp
 2414     5d/pop-to-ebp
 2415     c3/return
 2416 
 2417 test-convert-function-with-local-var-in-mem-after-block:
 2418     # . prologue
 2419     55/push-ebp
 2420     89/<- %ebp 4/r32/esp
 2421     # setup
 2422     (clear-stream _test-input-stream)
 2423     (clear-stream $_test-input-buffered-file->buffer)
 2424     (clear-stream _test-output-stream)
 2425     (clear-stream $_test-output-buffered-file->buffer)
 2426     #
 2427     (write _test-input-stream "fn foo {\n")
 2428     (write _test-input-stream "  {\n")
 2429     (write _test-input-stream "    var y: int\n")
 2430     (write _test-input-stream "  }\n")
 2431     (write _test-input-stream "  var x: int\n")
 2432     (write _test-input-stream "  increment x\n")
 2433     (write _test-input-stream "}\n")
 2434     # convert
 2435     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2436     (flush _test-output-buffered-file)
 2437 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2443     # check output
 2444     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 2445     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 2446     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 2447     (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")
 2448     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 2449     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 2450     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 2451     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 2452     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 2453     (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")
 2454     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 2455     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 2456     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 2457     (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")
 2458     (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")
 2459     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 2460     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 2461     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 2462     (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")
 2463     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 2464     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 2465     # . epilogue
 2466     89/<- %esp 5/r32/ebp
 2467     5d/pop-to-ebp
 2468     c3/return
 2469 
 2470 test-convert-function-with-local-var-in-named-block:
 2471     # . prologue
 2472     55/push-ebp
 2473     89/<- %ebp 4/r32/esp
 2474     # setup
 2475     (clear-stream _test-input-stream)
 2476     (clear-stream $_test-input-buffered-file->buffer)
 2477     (clear-stream _test-output-stream)
 2478     (clear-stream $_test-output-buffered-file->buffer)
 2479     #
 2480     (write _test-input-stream "fn foo {\n")
 2481     (write _test-input-stream "  $bar: {\n")
 2482     (write _test-input-stream "    var x: int\n")
 2483     (write _test-input-stream "    increment x\n")
 2484     (write _test-input-stream "  }\n")
 2485     (write _test-input-stream "}\n")
 2486     # convert
 2487     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2488     (flush _test-output-buffered-file)
 2489 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2495     # check output
 2496     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 2497     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 2498     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 2499     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 2500     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 2501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 2502     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 2503     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 2504     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 2505     (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")
 2506     (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")
 2507     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 2508     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 2509     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 2510     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 2511     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 2512     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 2513     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 2514     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 2515     # . epilogue
 2516     89/<- %esp 5/r32/ebp
 2517     5d/pop-to-ebp
 2518     c3/return
 2519 
 2520 test-unknown-variable-in-named-block:
 2521     # . prologue
 2522     55/push-ebp
 2523     89/<- %ebp 4/r32/esp
 2524     # setup
 2525     (clear-stream _test-input-stream)
 2526     (clear-stream $_test-input-buffered-file->buffer)
 2527     (clear-stream _test-output-stream)
 2528     (clear-stream $_test-output-buffered-file->buffer)
 2529     (clear-stream _test-error-stream)
 2530     (clear-stream $_test-error-buffered-file->buffer)
 2531     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2532     68/push 0/imm32
 2533     68/push 0/imm32
 2534     89/<- %edx 4/r32/esp
 2535     (tailor-exit-descriptor %edx 0x10)
 2536     #
 2537     (write _test-input-stream "fn foo {\n")
 2538     (write _test-input-stream "  $a: {\n")
 2539     (write _test-input-stream "    compare x, 0\n")
 2540     (write _test-input-stream "  }\n")
 2541     (write _test-input-stream "}\n")
 2542     # convert
 2543     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2544     # registers except esp clobbered at this point
 2545     # restore ed
 2546     89/<- %edx 4/r32/esp
 2547     (flush _test-output-buffered-file)
 2548     (flush _test-error-buffered-file)
 2549 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 2555     # check output
 2556     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 2557     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 2558     # check that stop(1) was called
 2559     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 2560     # don't restore from ebp
 2561     81 0/subop/add %esp 8/imm32
 2562     # . epilogue
 2563     5d/pop-to-ebp
 2564     c3/return
 2565 
 2566 test-always-shadow-outermost-reg-vars-in-function:
 2567     # . prologue
 2568     55/push-ebp
 2569     89/<- %ebp 4/r32/esp
 2570     # setup
 2571     (clear-stream _test-input-stream)
 2572     (clear-stream $_test-input-buffered-file->buffer)
 2573     (clear-stream _test-output-stream)
 2574     (clear-stream $_test-output-buffered-file->buffer)
 2575     #
 2576     (write _test-input-stream "fn foo {\n")
 2577     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2578     (write _test-input-stream "}\n")
 2579     # convert
 2580     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2581     (flush _test-output-buffered-file)
 2582 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2588     # check output
 2589     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 2590     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 2591     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 2592     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 2593     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 2594     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 2595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 2596     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 2597     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 2598     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 2599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 2600     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 2601     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 2602     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 2603     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 2604     # . epilogue
 2605     89/<- %esp 5/r32/ebp
 2606     5d/pop-to-ebp
 2607     c3/return
 2608 
 2609 _pending-test-clobber-dead-local:
 2610     # . prologue
 2611     55/push-ebp
 2612     89/<- %ebp 4/r32/esp
 2613     # setup
 2614     (clear-stream _test-input-stream)
 2615     (clear-stream $_test-input-buffered-file->buffer)
 2616     (clear-stream _test-output-stream)
 2617     (clear-stream $_test-output-buffered-file->buffer)
 2618     #
 2619     (write _test-input-stream "fn foo {\n")
 2620     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2621     (write _test-input-stream "  {\n")
 2622     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2623     (write _test-input-stream "  }\n")
 2624     (write _test-input-stream "}\n")
 2625     # convert
 2626     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2627     (flush _test-output-buffered-file)
 2628 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2634     # check output
 2635     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-clobber-dead-local/0")
 2636     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-clobber-dead-local/1")
 2637     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-clobber-dead-local/2")
 2638     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-clobber-dead-local/3")
 2639     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-clobber-dead-local/4")
 2640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-clobber-dead-local/5")
 2641     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-clobber-dead-local/6")
 2642     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-clobber-dead-local/7")
 2643     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-clobber-dead-local/8")
 2644     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-clobber-dead-local/9")
 2645     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-clobber-dead-local/10")  # no push/pop here
 2646     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-clobber-dead-local/11")
 2647     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-clobber-dead-local/12")
 2648     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-clobber-dead-local/13")
 2649     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-clobber-dead-local/14")
 2650     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-clobber-dead-local/15")
 2651     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-clobber-dead-local/16")
 2652     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-clobber-dead-local/17")
 2653     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-clobber-dead-local/18")
 2654     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-clobber-dead-local/19")
 2655     # . epilogue
 2656     89/<- %esp 5/r32/ebp
 2657     5d/pop-to-ebp
 2658     c3/return
 2659 
 2660 test-shadow-live-local:
 2661     # . prologue
 2662     55/push-ebp
 2663     89/<- %ebp 4/r32/esp
 2664     # setup
 2665     (clear-stream _test-input-stream)
 2666     (clear-stream $_test-input-buffered-file->buffer)
 2667     (clear-stream _test-output-stream)
 2668     (clear-stream $_test-output-buffered-file->buffer)
 2669     #
 2670     (write _test-input-stream "fn foo {\n")
 2671     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2672     (write _test-input-stream "  {\n")
 2673     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2674     (write _test-input-stream "  }\n")
 2675     (write _test-input-stream "  x <- increment\n")
 2676     (write _test-input-stream "}\n")
 2677     # convert
 2678     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2679     (flush _test-output-buffered-file)
 2680 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2686     # check output
 2687     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-live-local/0")
 2688     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-live-local/1")
 2689     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-live-local/2")
 2690     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-live-local/3")
 2691     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-live-local/4")
 2692     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-live-local/5")
 2693     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-live-local/6")
 2694     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-live-local/7")
 2695     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-live-local/8")
 2696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-live-local/9")
 2697     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-live-local/10")
 2698     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-live-local/11")
 2699     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-live-local/12")
 2700     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-live-local/13")
 2701     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-live-local/14")
 2702     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-live-local/15")
 2703     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-live-local/16")
 2704     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-live-local/17")
 2705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-live-local/18")
 2706     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-live-local/19")
 2707     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-live-local/20")
 2708     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-live-local/21")
 2709     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-live-local/22")
 2710     # . epilogue
 2711     89/<- %esp 5/r32/ebp
 2712     5d/pop-to-ebp
 2713     c3/return
 2714 
 2715 test-shadow-name:
 2716     # . prologue
 2717     55/push-ebp
 2718     89/<- %ebp 4/r32/esp
 2719     # setup
 2720     (clear-stream _test-input-stream)
 2721     (clear-stream $_test-input-buffered-file->buffer)
 2722     (clear-stream _test-output-stream)
 2723     (clear-stream $_test-output-buffered-file->buffer)
 2724     #
 2725     (write _test-input-stream "fn foo {\n")
 2726     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2727     (write _test-input-stream "  {\n")
 2728     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 2729     (write _test-input-stream "  }\n")
 2730     (write _test-input-stream "  x <- increment\n")
 2731     (write _test-input-stream "}\n")
 2732     # convert
 2733     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2734     (flush _test-output-buffered-file)
 2735 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2741     # check output
 2742     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 2743     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 2744     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 2745     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 2746     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 2747     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 2748     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 2749     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 2750     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 2751     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 2752     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 2753     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 2754     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 2755     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 2756     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 2757     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 2758     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 2759     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 2760     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 2761     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 2762     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 2763     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 2764     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 2765     # . epilogue
 2766     89/<- %esp 5/r32/ebp
 2767     5d/pop-to-ebp
 2768     c3/return
 2769 
 2770 test-shadow-name-2:
 2771     # . prologue
 2772     55/push-ebp
 2773     89/<- %ebp 4/r32/esp
 2774     # setup
 2775     (clear-stream _test-input-stream)
 2776     (clear-stream $_test-input-buffered-file->buffer)
 2777     (clear-stream _test-output-stream)
 2778     (clear-stream $_test-output-buffered-file->buffer)
 2779     #
 2780     (write _test-input-stream "fn foo {\n")
 2781     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2782     (write _test-input-stream "  {\n")
 2783     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 2784     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 2785     (write _test-input-stream "  }\n")
 2786     (write _test-input-stream "  x <- increment\n")
 2787     (write _test-input-stream "}\n")
 2788     # convert
 2789     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2790     (flush _test-output-buffered-file)
 2791 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2797     # check output
 2798     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 2799     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 2800     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 2801     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 2802     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 2803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 2804     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 2805     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 2806     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 2807     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 2808     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 2809     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 2810     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 2811     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 2812     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 2813     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 2814     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 2815     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 2816     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 2817     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 2818     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 2819     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 2820     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 2821     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 2822     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 2823     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 2824     # . epilogue
 2825     89/<- %esp 5/r32/ebp
 2826     5d/pop-to-ebp
 2827     c3/return
 2828 
 2829 test-do-not-spill-same-register-in-block:
 2830     # . prologue
 2831     55/push-ebp
 2832     89/<- %ebp 4/r32/esp
 2833     # setup
 2834     (clear-stream _test-input-stream)
 2835     (clear-stream $_test-input-buffered-file->buffer)
 2836     (clear-stream _test-output-stream)
 2837     (clear-stream $_test-output-buffered-file->buffer)
 2838     #
 2839     (write _test-input-stream "fn foo {\n")
 2840     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2841     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2842     (write _test-input-stream "  y <- increment\n")
 2843     (write _test-input-stream "}\n")
 2844     # convert
 2845     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2846     (flush _test-output-buffered-file)
 2847 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2853     # check output
 2854     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 2855     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 2856     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 2857     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 2858     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 2859     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 2860     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 2861     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 2862     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 2863     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 2864     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 2865     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 2866     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 2867     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 2868     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 2869     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 2870     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 2871     # . epilogue
 2872     89/<- %esp 5/r32/ebp
 2873     5d/pop-to-ebp
 2874     c3/return
 2875 
 2876 test-spill-different-register-in-block:
 2877     # . prologue
 2878     55/push-ebp
 2879     89/<- %ebp 4/r32/esp
 2880     # setup
 2881     (clear-stream _test-input-stream)
 2882     (clear-stream $_test-input-buffered-file->buffer)
 2883     (clear-stream _test-output-stream)
 2884     (clear-stream $_test-output-buffered-file->buffer)
 2885     #
 2886     (write _test-input-stream "fn foo {\n")
 2887     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2888     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2889     (write _test-input-stream "  y <- increment\n")
 2890     (write _test-input-stream "}\n")
 2891     # convert
 2892     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2893     (flush _test-output-buffered-file)
 2894 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2900     # check output
 2901     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 2902     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 2903     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 2904     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 2905     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 2906     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 2907     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 2908     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 2909     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 2910     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 2911     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 2912     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 2913     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 2914     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 2915     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 2916     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 2917     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 2918     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 2919     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 2920     # . epilogue
 2921     89/<- %esp 5/r32/ebp
 2922     5d/pop-to-ebp
 2923     c3/return
 2924 
 2925 test-shadow-live-output:
 2926     # . prologue
 2927     55/push-ebp
 2928     89/<- %ebp 4/r32/esp
 2929     # setup
 2930     (clear-stream _test-input-stream)
 2931     (clear-stream $_test-input-buffered-file->buffer)
 2932     (clear-stream _test-output-stream)
 2933     (clear-stream $_test-output-buffered-file->buffer)
 2934     #
 2935     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 2936     (write _test-input-stream "  x <- copy 3\n")
 2937     (write _test-input-stream "  {\n")
 2938     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 2939     (write _test-input-stream "  }\n")
 2940     (write _test-input-stream "  x <- increment\n")
 2941     (write _test-input-stream "}\n")
 2942     # convert
 2943     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2944     (flush _test-output-buffered-file)
 2945 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 2951     # check output
 2952     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-live-output/0")
 2953     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-live-output/1")
 2954     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-live-output/2")
 2955     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-live-output/3")
 2956     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-live-output/4")
 2957     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-live-output/5")
 2958     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-live-output/7")  # no push because it's an output reg
 2959     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-live-output/8")
 2960     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-live-output/9")
 2961     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-live-output/10")
 2962     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-live-output/11")
 2963     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-live-output/12")
 2964     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-live-output/13")
 2965     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-live-output/14")
 2966     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-live-output/15")
 2967     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-live-output/17")
 2968     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-live-output/18")
 2969     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-live-output/19")
 2970     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-live-output/20")
 2971     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-live-output/21")
 2972     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-live-output/21")
 2973     # . epilogue
 2974     89/<- %esp 5/r32/ebp
 2975     5d/pop-to-ebp
 2976     c3/return
 2977 
 2978 test-stmt-defines-output-in-same-register-as-inout:
 2979     # . prologue
 2980     55/push-ebp
 2981     89/<- %ebp 4/r32/esp
 2982     # setup
 2983     (clear-stream _test-input-stream)
 2984     (clear-stream $_test-input-buffered-file->buffer)
 2985     (clear-stream _test-output-stream)
 2986     (clear-stream $_test-output-buffered-file->buffer)
 2987     (clear-stream _test-error-stream)
 2988     (clear-stream $_test-error-buffered-file->buffer)
 2989     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2990     68/push 0/imm32
 2991     68/push 0/imm32
 2992     89/<- %edx 4/r32/esp
 2993     (tailor-exit-descriptor %edx 0x10)
 2994     #
 2995     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 2996     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2997     (write _test-input-stream "  x <- copy y\n")  # writing to a fn output is currently the only way for a statement to define a new var
 2998     (write _test-input-stream "}\n")
 2999     # convert
 3000     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3001     # registers except esp clobbered at this point
 3002     # restore ed
 3003     89/<- %edx 4/r32/esp
 3004     (flush _test-output-buffered-file)
 3005     (flush _test-error-buffered-file)
 3006 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 3012     # no error; we looked up 'y' correctly before pushing the binding for 'x'
 3013     (check-stream-equal _test-error-stream  ""  "F - test-stmt-defines-output-in-same-register-as-inout: error stream should be empty")
 3014     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 3015     # don't restore from ebp
 3016     81 0/subop/add %esp 8/imm32
 3017     # . epilogue
 3018     5d/pop-to-ebp
 3019     c3/return
 3020 
 3021 test-local-clobbered-by-fn-output:
 3022     # . prologue
 3023     55/push-ebp
 3024     89/<- %ebp 4/r32/esp
 3025     # setup
 3026     (clear-stream _test-input-stream)
 3027     (clear-stream $_test-input-buffered-file->buffer)
 3028     (clear-stream _test-output-stream)
 3029     (clear-stream $_test-output-buffered-file->buffer)
 3030     #
 3031     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 3032     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 3033     (write _test-input-stream "  x <- copy y\n")
 3034     (write _test-input-stream "}\n")
 3035     # convert
 3036     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3037     (flush _test-output-buffered-file)
 3038 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3044     # check output
 3045     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-local-clobbered-by-fn-output/0")
 3046     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-local-clobbered-by-fn-output/1")
 3047     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-local-clobbered-by-fn-output/2")
 3048     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-local-clobbered-by-fn-output/3")
 3049     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-local-clobbered-by-fn-output/4")
 3050     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-local-clobbered-by-fn-output/5")
 3051     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-local-clobbered-by-fn-output/6")  # no push because it's an output reg
 3052     (check-next-stream-line-equal _test-output-stream "    89/<- %ecx 0x00000001/r32"  "F - test-local-clobbered-by-fn-output/7")
 3053     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-local-clobbered-by-fn-output/8")
 3054     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-local-clobbered-by-fn-output/9")
 3055     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-local-clobbered-by-fn-output/10")
 3056     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-local-clobbered-by-fn-output/11")
 3057     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-local-clobbered-by-fn-output/12")
 3058     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-local-clobbered-by-fn-output/13")
 3059     # . epilogue
 3060     89/<- %esp 5/r32/ebp
 3061     5d/pop-to-ebp
 3062     c3/return
 3063 
 3064 test-read-output:
 3065     # . prologue
 3066     55/push-ebp
 3067     89/<- %ebp 4/r32/esp
 3068     # setup
 3069     (clear-stream _test-input-stream)
 3070     (clear-stream $_test-input-buffered-file->buffer)
 3071     (clear-stream _test-output-stream)
 3072     (clear-stream $_test-output-buffered-file->buffer)
 3073     #
 3074     (write _test-input-stream "fn foo -> x/ecx: int {\n")
 3075     (write _test-input-stream "  x <- copy 0x34\n")
 3076     (write _test-input-stream "  compare x, 0x35\n")
 3077     (write _test-input-stream "}\n")
 3078     # convert
 3079     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3080     (flush _test-output-buffered-file)
 3081 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3087     # check output
 3088     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-read-output/0")
 3089     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-read-output/1")
 3090     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-read-output/2")
 3091     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-read-output/3")
 3092     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-read-output/4")
 3093     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-read-output/5")
 3094     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-read-output/6")
 3095     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0x35/imm32"  "F - test-read-output/7")
 3096     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-read-output/8")
 3097     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-read-output/9")
 3098     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-read-output/10")
 3099     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-read-output/11")
 3100     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-read-output/12")
 3101     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-read-output/13")
 3102     # . epilogue
 3103     89/<- %esp 5/r32/ebp
 3104     5d/pop-to-ebp
 3105     c3/return
 3106 
 3107 test-fn-output-written-in-inner-block:
 3108     # . prologue
 3109     55/push-ebp
 3110     89/<- %ebp 4/r32/esp
 3111     # setup
 3112     (clear-stream _test-input-stream)
 3113     (clear-stream $_test-input-buffered-file->buffer)
 3114     (clear-stream _test-output-stream)
 3115     (clear-stream $_test-output-buffered-file->buffer)
 3116     #
 3117     (write _test-input-stream "fn foo -> out/edi: int {\n")
 3118     (write _test-input-stream "  var a/eax: int <- copy 3\n")  # define outer local
 3119     (write _test-input-stream "  {\n")
 3120     (write _test-input-stream "    var a/ecx: int <- copy 4\n")  # shadow outer local
 3121     (write _test-input-stream "    out <- copy a\n")  # write to fn output
 3122     (write _test-input-stream "  }\n")
 3123     (write _test-input-stream "  compare a, 0\n")  # use outer local
 3124     (write _test-input-stream "}\n")
 3125     # convert
 3126     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3127     (flush _test-output-buffered-file)
 3128 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3134     # no error; defining 'out' didn't interfere with the reclamation of 'b'
 3135     # check output
 3136     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-fn-output-written-in-inner-block/0")
 3137     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-fn-output-written-in-inner-block/1")
 3138     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-fn-output-written-in-inner-block/2")
 3139     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-fn-output-written-in-inner-block/3")
 3140     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-fn-output-written-in-inner-block/4")
 3141     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-fn-output-written-in-inner-block/5")
 3142     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-fn-output-written-in-inner-block/6")
 3143     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-fn-output-written-in-inner-block/7")
 3144     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-fn-output-written-in-inner-block/8")
 3145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-fn-output-written-in-inner-block/9")
 3146     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-fn-output-written-in-inner-block/10")
 3147     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-fn-output-written-in-inner-block/10")
 3148     (check-next-stream-line-equal _test-output-stream "      89/<- %edi 0x00000001/r32"  "F - test-fn-output-written-in-inner-block/11")
 3149     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx"  "F - test-fn-output-written-in-inner-block/12")
 3150     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-fn-output-written-in-inner-block/13")
 3151     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-fn-output-written-in-inner-block/14")
 3152     (check-next-stream-line-equal _test-output-stream "    3d/compare-eax-with 0/imm32"  "F - test-fn-output-written-in-inner-block/15")
 3153     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-fn-output-written-in-inner-block/16")
 3154     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-fn-output-written-in-inner-block/17")
 3155     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-fn-output-written-in-inner-block/18")
 3156     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-fn-output-written-in-inner-block/19")
 3157     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-fn-output-written-in-inner-block/20")
 3158     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-fn-output-written-in-inner-block/21")
 3159     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-fn-output-written-in-inner-block/22")
 3160     # . epilogue
 3161     89/<- %esp 5/r32/ebp
 3162     5d/pop-to-ebp
 3163     c3/return
 3164 
 3165 test-convert-function-with-branches-in-block:
 3166     # . prologue
 3167     55/push-ebp
 3168     89/<- %ebp 4/r32/esp
 3169     # setup
 3170     (clear-stream _test-input-stream)
 3171     (clear-stream $_test-input-buffered-file->buffer)
 3172     (clear-stream _test-output-stream)
 3173     (clear-stream $_test-output-buffered-file->buffer)
 3174     #
 3175     (write _test-input-stream "fn foo x: int {\n")
 3176     (write _test-input-stream "  {\n")
 3177     (write _test-input-stream "    break-if->=\n")
 3178     (write _test-input-stream "    loop-if-addr<\n")
 3179     (write _test-input-stream "    increment x\n")
 3180     (write _test-input-stream "    loop\n")
 3181     (write _test-input-stream "  }\n")
 3182     (write _test-input-stream "}\n")
 3183     # convert
 3184     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3185     (flush _test-output-buffered-file)
 3186 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3192     # check output
 3193     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3194     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3195     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3196     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3197     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3198     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3199     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3200     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3201     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3202     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3203     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3204     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3205     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3206     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3207     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3208     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3209     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3210     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3211     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3212     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3213     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3214     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3216     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3219     # . epilogue
 3220     89/<- %esp 5/r32/ebp
 3221     5d/pop-to-ebp
 3222     c3/return
 3223 
 3224 test-convert-function-with-branches-in-block-2:
 3225     # . prologue
 3226     55/push-ebp
 3227     89/<- %ebp 4/r32/esp
 3228     # setup
 3229     (clear-stream _test-input-stream)
 3230     (clear-stream $_test-input-buffered-file->buffer)
 3231     (clear-stream _test-output-stream)
 3232     (clear-stream $_test-output-buffered-file->buffer)
 3233     #
 3234     (write _test-input-stream "fn foo x: int {\n")
 3235     (write _test-input-stream "  {\n")
 3236     (write _test-input-stream "    break-if->=\n")
 3237     (write _test-input-stream "    loop-if-float<\n")
 3238     (write _test-input-stream "    increment x\n")
 3239     (write _test-input-stream "    loop\n")
 3240     (write _test-input-stream "  }\n")
 3241     (write _test-input-stream "}\n")
 3242     # convert
 3243     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3244     (flush _test-output-buffered-file)
 3245 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3251     # check output
 3252     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 3253     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 3254     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 3255     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 3256     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 3257     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 3258     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 3259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 3260     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 3261     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 3262     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 3263     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 3264     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 3265     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 3266     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 3267     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 3268     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 3269     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 3270     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 3271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 3272     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 3273     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 3274     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 3275     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 3276     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 3277     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 3278     # . epilogue
 3279     89/<- %esp 5/r32/ebp
 3280     5d/pop-to-ebp
 3281     c3/return
 3282 
 3283 test-convert-function-with-branches-in-named-block:
 3284     # . prologue
 3285     55/push-ebp
 3286     89/<- %ebp 4/r32/esp
 3287     # setup
 3288     (clear-stream _test-input-stream)
 3289     (clear-stream $_test-input-buffered-file->buffer)
 3290     (clear-stream _test-output-stream)
 3291     (clear-stream $_test-output-buffered-file->buffer)
 3292     #
 3293     (write _test-input-stream "fn foo x: int {\n")
 3294     (write _test-input-stream "  $bar: {\n")
 3295     (write _test-input-stream "    break-if->= $bar\n")
 3296     (write _test-input-stream "    loop-if-addr< $bar\n")
 3297     (write _test-input-stream "    increment x\n")
 3298     (write _test-input-stream "    loop\n")
 3299     (write _test-input-stream "  }\n")
 3300     (write _test-input-stream "}\n")
 3301     # convert
 3302     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3303     (flush _test-output-buffered-file)
 3304 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3310     # check output
 3311     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 3312     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 3313     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 3314     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 3315     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 3316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 3317     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 3318     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 3319     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 3320     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 3321     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 3322     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 3323     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 3324     (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")
 3325     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 3326     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 3327     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 3328     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 3329     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 3330     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 3331     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 3332     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 3333     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 3334     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 3335     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 3336     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 3337     # . epilogue
 3338     89/<- %esp 5/r32/ebp
 3339     5d/pop-to-ebp
 3340     c3/return
 3341 
 3342 test-convert-function-with-var-in-nested-block:
 3343     # . prologue
 3344     55/push-ebp
 3345     89/<- %ebp 4/r32/esp
 3346     # setup
 3347     (clear-stream _test-input-stream)
 3348     (clear-stream $_test-input-buffered-file->buffer)
 3349     (clear-stream _test-output-stream)
 3350     (clear-stream $_test-output-buffered-file->buffer)
 3351     #
 3352     (write _test-input-stream "fn foo x: int {\n")
 3353     (write _test-input-stream "  {\n")
 3354     (write _test-input-stream "    {\n")
 3355     (write _test-input-stream "      var x: int\n")
 3356     (write _test-input-stream "      increment x\n")
 3357     (write _test-input-stream "    }\n")
 3358     (write _test-input-stream "  }\n")
 3359     (write _test-input-stream "}\n")
 3360     # convert
 3361     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3362     (flush _test-output-buffered-file)
 3363 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3369     # check output
 3370     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 3371     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 3372     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 3373     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 3374     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 3375     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 3376     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 3377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 3378     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 3379     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 3380     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 3381     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 3382     (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")
 3383     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 3384     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 3385     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 3386     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 3387     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 3388     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 3389     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 3390     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 3391     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 3392     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 3393     # . epilogue
 3394     89/<- %esp 5/r32/ebp
 3395     5d/pop-to-ebp
 3396     c3/return
 3397 
 3398 test-convert-function-with-multiple-vars-in-nested-blocks:
 3399     # . prologue
 3400     55/push-ebp
 3401     89/<- %ebp 4/r32/esp
 3402     # setup
 3403     (clear-stream _test-input-stream)
 3404     (clear-stream $_test-input-buffered-file->buffer)
 3405     (clear-stream _test-output-stream)
 3406     (clear-stream $_test-output-buffered-file->buffer)
 3407     #
 3408     (write _test-input-stream "fn foo x: int {\n")
 3409     (write _test-input-stream "  {\n")
 3410     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 3411     (write _test-input-stream "    {\n")
 3412     (write _test-input-stream "      var y: int\n")
 3413     (write _test-input-stream "      x <- add y\n")
 3414     (write _test-input-stream "    }\n")
 3415     (write _test-input-stream "  }\n")
 3416     (write _test-input-stream "}\n")
 3417     # convert
 3418     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3419     (flush _test-output-buffered-file)
 3420 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3426     # check output
 3427     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 3428     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 3429     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 3430     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 3431     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 3432     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 3433     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 3434     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 3435     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 3436     (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")
 3437     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 3438     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 3439     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 3440     (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")
 3441     (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")
 3442     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 3443     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 3444     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 3445     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 3446     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 3447     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 3448     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 3449     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 3450     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 3451     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 3452     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 3453     # . epilogue
 3454     89/<- %esp 5/r32/ebp
 3455     5d/pop-to-ebp
 3456     c3/return
 3457 
 3458 test-convert-function-with-branches-and-local-vars:
 3459     # A conditional 'break' after a 'var' in a block is converted into a
 3460     # nested block that performs all necessary cleanup before jumping. This
 3461     # results in some ugly code duplication.
 3462     # . prologue
 3463     55/push-ebp
 3464     89/<- %ebp 4/r32/esp
 3465     # setup
 3466     (clear-stream _test-input-stream)
 3467     (clear-stream $_test-input-buffered-file->buffer)
 3468     (clear-stream _test-output-stream)
 3469     (clear-stream $_test-output-buffered-file->buffer)
 3470     #
 3471     (write _test-input-stream "fn foo {\n")
 3472     (write _test-input-stream "  {\n")
 3473     (write _test-input-stream "    var x: int\n")
 3474     (write _test-input-stream "    break-if->=\n")
 3475     (write _test-input-stream "    increment x\n")
 3476     (write _test-input-stream "  }\n")
 3477     (write _test-input-stream "}\n")
 3478     # convert
 3479     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3480     (flush _test-output-buffered-file)
 3481 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3487     # check output
 3488     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 3489     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 3490     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 3491     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 3492     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 3493     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 3494     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 3495     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 3496     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 3497     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 3498     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 3499     (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")
 3500     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 3501     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 3502     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 3503     (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")
 3504     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 3505     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 3506     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 3507     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 3508     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 3509     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 3510     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 3511     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 3512     # . epilogue
 3513     89/<- %esp 5/r32/ebp
 3514     5d/pop-to-ebp
 3515     c3/return
 3516 
 3517 test-convert-function-with-conditional-loops-and-local-vars:
 3518     # A conditional 'loop' after a 'var' in a block is converted into a nested
 3519     # block that performs all necessary cleanup before jumping. This results
 3520     # in some ugly code duplication.
 3521     # . prologue
 3522     55/push-ebp
 3523     89/<- %ebp 4/r32/esp
 3524     # setup
 3525     (clear-stream _test-input-stream)
 3526     (clear-stream $_test-input-buffered-file->buffer)
 3527     (clear-stream _test-output-stream)
 3528     (clear-stream $_test-output-buffered-file->buffer)
 3529     #
 3530     (write _test-input-stream "fn foo {\n")
 3531     (write _test-input-stream "  {\n")
 3532     (write _test-input-stream "    var x: int\n")
 3533     (write _test-input-stream "    loop-if->=\n")
 3534     (write _test-input-stream "    increment x\n")
 3535     (write _test-input-stream "  }\n")
 3536     (write _test-input-stream "}\n")
 3537     # convert
 3538     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3539     (flush _test-output-buffered-file)
 3540 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3546     # check output
 3547     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 3548     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 3549     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 3550     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 3551     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 3552     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 3553     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 3554     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 3555     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 3556     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 3557     (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")
 3558     (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")
 3559     (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")
 3560     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 3561     (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")
 3562     (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")
 3563     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 3564     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 3565     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 3566     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 3567     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 3568     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 3569     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 3570     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 3571     # . epilogue
 3572     89/<- %esp 5/r32/ebp
 3573     5d/pop-to-ebp
 3574     c3/return
 3575 
 3576 test-convert-function-with-unconditional-loops-and-local-vars:
 3577     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 3578     # regular block cleanup. Any instructions after 'loop' are dead and
 3579     # therefore skipped.
 3580     # . prologue
 3581     55/push-ebp
 3582     89/<- %ebp 4/r32/esp
 3583     # setup
 3584     (clear-stream _test-input-stream)
 3585     (clear-stream $_test-input-buffered-file->buffer)
 3586     (clear-stream _test-output-stream)
 3587     (clear-stream $_test-output-buffered-file->buffer)
 3588     #
 3589     (write _test-input-stream "fn foo {\n")
 3590     (write _test-input-stream "  {\n")
 3591     (write _test-input-stream "    var x: int\n")
 3592     (write _test-input-stream "    loop\n")
 3593     (write _test-input-stream "    increment x\n")
 3594     (write _test-input-stream "  }\n")
 3595     (write _test-input-stream "}\n")
 3596     # convert
 3597     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3598     (flush _test-output-buffered-file)
 3599 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3605     # check output
 3606     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 3607     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 3608     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 3609     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 3610     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 3611     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 3612     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 3613     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 3614     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 3615     (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")
 3616     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 3617     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 3618     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 3619     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 3620     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 3621     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 3622     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 3623     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 3624     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 3625     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 3626     # . epilogue
 3627     89/<- %esp 5/r32/ebp
 3628     5d/pop-to-ebp
 3629     c3/return
 3630 
 3631 test-convert-function-with-branches-and-loops-and-local-vars:
 3632     # . prologue
 3633     55/push-ebp
 3634     89/<- %ebp 4/r32/esp
 3635     # setup
 3636     (clear-stream _test-input-stream)
 3637     (clear-stream $_test-input-buffered-file->buffer)
 3638     (clear-stream _test-output-stream)
 3639     (clear-stream $_test-output-buffered-file->buffer)
 3640     #
 3641     (write _test-input-stream "fn foo {\n")
 3642     (write _test-input-stream "  {\n")
 3643     (write _test-input-stream "    var x: int\n")
 3644     (write _test-input-stream "    break-if->=\n")
 3645     (write _test-input-stream "    increment x\n")
 3646     (write _test-input-stream "    loop\n")
 3647     (write _test-input-stream "  }\n")
 3648     (write _test-input-stream "}\n")
 3649     # convert
 3650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3651     (flush _test-output-buffered-file)
 3652 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3658     # check output
 3659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 3660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 3661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 3662     (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")
 3663     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 3664     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 3665     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 3666     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 3667     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 3668     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 3669     (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")
 3670     (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")
 3671     (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")
 3672     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 3673     (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")
 3674     (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")
 3675     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 3676     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 3677     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 3678     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 3679     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 3680     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 3681     (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")
 3682     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 3683     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 3684     # . epilogue
 3685     89/<- %esp 5/r32/ebp
 3686     5d/pop-to-ebp
 3687     c3/return
 3688 
 3689 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 3690     # . prologue
 3691     55/push-ebp
 3692     89/<- %ebp 4/r32/esp
 3693     # setup
 3694     (clear-stream _test-input-stream)
 3695     (clear-stream $_test-input-buffered-file->buffer)
 3696     (clear-stream _test-output-stream)
 3697     (clear-stream $_test-output-buffered-file->buffer)
 3698     #
 3699     (write _test-input-stream "fn foo {\n")
 3700     (write _test-input-stream "  a: {\n")
 3701     (write _test-input-stream "    var x: int\n")
 3702     (write _test-input-stream "    {\n")
 3703     (write _test-input-stream "      var y: int\n")
 3704     (write _test-input-stream "      break-if->= a\n")
 3705     (write _test-input-stream "      increment x\n")
 3706     (write _test-input-stream "      loop\n")
 3707     (write _test-input-stream "    }\n")
 3708     (write _test-input-stream "  }\n")
 3709     (write _test-input-stream "}\n")
 3710     # convert
 3711     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3712     (flush _test-output-buffered-file)
 3713 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3719     # check output
 3720     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 3721     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 3722     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 3723     (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")
 3724     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 3725     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 3726     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 3727     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 3728     (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")
 3729     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 3730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 3731     (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")
 3732     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 3733     (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")
 3734     (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")
 3735     (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")
 3736     (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")
 3737     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 3738     (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")
 3739     (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")
 3740     (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")
 3741     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 3742     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 3743     (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")
 3744     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 3745     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 3746     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 3747     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 3748     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 3749     (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")
 3750     (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")
 3751     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 3752     # . epilogue
 3753     89/<- %esp 5/r32/ebp
 3754     5d/pop-to-ebp
 3755     c3/return
 3756 
 3757 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 3758     # . prologue
 3759     55/push-ebp
 3760     89/<- %ebp 4/r32/esp
 3761     # setup
 3762     (clear-stream _test-input-stream)
 3763     (clear-stream $_test-input-buffered-file->buffer)
 3764     (clear-stream _test-output-stream)
 3765     (clear-stream $_test-output-buffered-file->buffer)
 3766     # non-local conditional branch from a block without a local variable,
 3767     # unwinding a local on the stack
 3768     (write _test-input-stream "fn foo {\n")
 3769     (write _test-input-stream "  a: {\n")
 3770     (write _test-input-stream "    var x: int\n")
 3771     (write _test-input-stream "    {\n")
 3772     (write _test-input-stream "      break-if->= a\n")
 3773     (write _test-input-stream "    }\n")
 3774     (write _test-input-stream "  }\n")
 3775     (write _test-input-stream "}\n")
 3776     # convert
 3777     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3778     (flush _test-output-buffered-file)
 3779 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3785     # check output
 3786     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 3787     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 3788     (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")
 3789     (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")
 3790     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 3791     (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")
 3792     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 3793     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 3794     (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")
 3795     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 3796     (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")
 3797     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 3798     (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")
 3799     (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")
 3800     (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")
 3801     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 3802     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 3803     (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")
 3804     (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")
 3805     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 3806     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 3807     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 3808     (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")
 3809     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 3810     (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")
 3811     (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")
 3812     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 3813     # . epilogue
 3814     89/<- %esp 5/r32/ebp
 3815     5d/pop-to-ebp
 3816     c3/return
 3817 
 3818 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 3819     # . prologue
 3820     55/push-ebp
 3821     89/<- %ebp 4/r32/esp
 3822     # setup
 3823     (clear-stream _test-input-stream)
 3824     (clear-stream $_test-input-buffered-file->buffer)
 3825     (clear-stream _test-output-stream)
 3826     (clear-stream $_test-output-buffered-file->buffer)
 3827     # non-local unconditional branch from a block without a local variable,
 3828     # unwinding a local on the stack
 3829     (write _test-input-stream "fn foo {\n")
 3830     (write _test-input-stream "  a: {\n")
 3831     (write _test-input-stream "    var x: int\n")
 3832     (write _test-input-stream "    {\n")
 3833     (write _test-input-stream "      break a\n")
 3834     (write _test-input-stream "    }\n")
 3835     (write _test-input-stream "  }\n")
 3836     (write _test-input-stream "}\n")
 3837     # convert
 3838     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3839     (flush _test-output-buffered-file)
 3840 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3846     # check output
 3847     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 3848     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 3849     (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")
 3850     (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")
 3851     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 3852     (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")
 3853     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 3854     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 3855     (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")
 3856     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 3857     (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")
 3858     (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")
 3859     (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")
 3860     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 3861     (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")
 3862     (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")
 3863     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 3864     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 3865     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 3866     (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")
 3867     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 3868     (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")
 3869     (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")
 3870     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 3871     # . epilogue
 3872     89/<- %esp 5/r32/ebp
 3873     5d/pop-to-ebp
 3874     c3/return
 3875 
 3876 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 3877     # . prologue
 3878     55/push-ebp
 3879     89/<- %ebp 4/r32/esp
 3880     # setup
 3881     (clear-stream _test-input-stream)
 3882     (clear-stream $_test-input-buffered-file->buffer)
 3883     (clear-stream _test-output-stream)
 3884     (clear-stream $_test-output-buffered-file->buffer)
 3885     #
 3886     (write _test-input-stream "fn foo {\n")
 3887     (write _test-input-stream "  a: {\n")
 3888     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 3889     (write _test-input-stream "    {\n")
 3890     (write _test-input-stream "      break a\n")
 3891     (write _test-input-stream "    }\n")
 3892     (write _test-input-stream "  }\n")
 3893     (write _test-input-stream "}\n")
 3894     # convert
 3895     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3896     (flush _test-output-buffered-file)
 3897 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3903     # check output
 3904     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 3905     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 3906     (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")
 3907     (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")
 3908     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 3909     (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")
 3910     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 3911     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 3912     (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")
 3913     (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")
 3914     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 3915     (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")
 3916     (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")
 3917     (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")
 3918     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 3919     (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")
 3920     (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")
 3921     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 3922     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 3923     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 3924     (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")
 3925     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 3926     (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")
 3927     (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")
 3928     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 3929     # . epilogue
 3930     89/<- %esp 5/r32/ebp
 3931     5d/pop-to-ebp
 3932     c3/return
 3933 
 3934 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 3935     # . prologue
 3936     55/push-ebp
 3937     89/<- %ebp 4/r32/esp
 3938     # setup
 3939     (clear-stream _test-input-stream)
 3940     (clear-stream $_test-input-buffered-file->buffer)
 3941     (clear-stream _test-output-stream)
 3942     (clear-stream $_test-output-buffered-file->buffer)
 3943     #
 3944     (write _test-input-stream "fn foo {\n")
 3945     (write _test-input-stream "  a: {\n")
 3946     (write _test-input-stream "    var x: int\n")
 3947     (write _test-input-stream "    {\n")
 3948     (write _test-input-stream "      var y: int\n")
 3949     (write _test-input-stream "      break a\n")
 3950     (write _test-input-stream "      increment x\n")
 3951     (write _test-input-stream "    }\n")
 3952     (write _test-input-stream "  }\n")
 3953     (write _test-input-stream "}\n")
 3954     # convert
 3955     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3956     (flush _test-output-buffered-file)
 3957 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 3963     # check output
 3964     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 3965     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 3966     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 3967     (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")
 3968     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 3969     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 3970     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 3971     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 3972     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 3973     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 3974     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 3975     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 3976     (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")
 3977     (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")
 3978     (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")
 3979     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 3980     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 3981     (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")
 3982     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 3983     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 3984     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 3985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 3986     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 3987     (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")
 3988     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 3989     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 3990     # . epilogue
 3991     89/<- %esp 5/r32/ebp
 3992     5d/pop-to-ebp
 3993     c3/return
 3994 
 3995 test-convert-function-with-unconditional-break-and-local-vars:
 3996     # . prologue
 3997     55/push-ebp
 3998     89/<- %ebp 4/r32/esp
 3999     # setup
 4000     (clear-stream _test-input-stream)
 4001     (clear-stream $_test-input-buffered-file->buffer)
 4002     (clear-stream _test-output-stream)
 4003     (clear-stream $_test-output-buffered-file->buffer)
 4004     #
 4005     (write _test-input-stream "fn foo {\n")
 4006     (write _test-input-stream "  {\n")
 4007     (write _test-input-stream "    var x: int\n")
 4008     (write _test-input-stream "    {\n")
 4009     (write _test-input-stream "      var y: int\n")
 4010     (write _test-input-stream "      break\n")
 4011     (write _test-input-stream "      increment x\n")
 4012     (write _test-input-stream "    }\n")
 4013     (write _test-input-stream "  }\n")
 4014     (write _test-input-stream "}\n")
 4015     # convert
 4016     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4017     (flush _test-output-buffered-file)
 4018 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4024     # check output
 4025     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 4026     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 4027     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 4028     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 4029     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 4030     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 4031     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 4032     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 4033     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 4034     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 4035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 4036     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 4037     (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")
 4038     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 4039     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 4040     (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")
 4041     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 4042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 4043     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 4044     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 4045     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 4046     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 4047     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 4048     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 4049     # . epilogue
 4050     89/<- %esp 5/r32/ebp
 4051     5d/pop-to-ebp
 4052     c3/return
 4053 
 4054 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 4055     # . prologue
 4056     55/push-ebp
 4057     89/<- %ebp 4/r32/esp
 4058     # setup
 4059     (clear-stream _test-input-stream)
 4060     (clear-stream $_test-input-buffered-file->buffer)
 4061     (clear-stream _test-output-stream)
 4062     (clear-stream $_test-output-buffered-file->buffer)
 4063     #
 4064     (write _test-input-stream "fn foo {\n")
 4065     (write _test-input-stream "  a: {\n")
 4066     (write _test-input-stream "    var x: int\n")
 4067     (write _test-input-stream "    {\n")
 4068     (write _test-input-stream "      var y: int\n")
 4069     (write _test-input-stream "      loop a\n")
 4070     (write _test-input-stream "      increment x\n")
 4071     (write _test-input-stream "    }\n")
 4072     (write _test-input-stream "  }\n")
 4073     (write _test-input-stream "}\n")
 4074     # convert
 4075     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4076     (flush _test-output-buffered-file)
 4077 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4083     # check output
 4084     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 4085     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 4086     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 4087     (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")
 4088     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 4089     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 4090     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 4091     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 4092     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 4093     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 4094     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 4095     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 4096     (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")
 4097     (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")
 4098     (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")
 4099     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 4100     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 4101     (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")
 4102     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 4103     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 4104     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 4105     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 4106     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 4107     (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")
 4108     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 4109     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 4110     # . epilogue
 4111     89/<- %esp 5/r32/ebp
 4112     5d/pop-to-ebp
 4113     c3/return
 4114 
 4115 test-convert-function-with-local-array-var-in-mem:
 4116     # . prologue
 4117     55/push-ebp
 4118     89/<- %ebp 4/r32/esp
 4119     # setup
 4120     (clear-stream _test-input-stream)
 4121     (clear-stream $_test-input-buffered-file->buffer)
 4122     (clear-stream _test-output-stream)
 4123     (clear-stream $_test-output-buffered-file->buffer)
 4124     #
 4125     (write _test-input-stream "fn foo {\n")
 4126     (write _test-input-stream "  var x: (array int 3)\n")
 4127     (write _test-input-stream "}\n")
 4128     # convert
 4129     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4130     (flush _test-output-buffered-file)
 4131 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4137     # check output
 4138     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 4139     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 4140     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 4141     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 4142     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 4143     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 4144     # define x
 4145     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 4146     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 4147     # reclaim x
 4148     (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")
 4149     #
 4150     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 4151     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 4152     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 4153     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 4154     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 4155     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 4156     # . epilogue
 4157     89/<- %esp 5/r32/ebp
 4158     5d/pop-to-ebp
 4159     c3/return
 4160 
 4161 test-array-size-in-hex:
 4162     # . prologue
 4163     55/push-ebp
 4164     89/<- %ebp 4/r32/esp
 4165     # setup
 4166     (clear-stream _test-input-stream)
 4167     (clear-stream $_test-input-buffered-file->buffer)
 4168     (clear-stream _test-output-stream)
 4169     (clear-stream $_test-output-buffered-file->buffer)
 4170     (clear-stream _test-error-stream)
 4171     (clear-stream $_test-error-buffered-file->buffer)
 4172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 4173     68/push 0/imm32
 4174     68/push 0/imm32
 4175     89/<- %edx 4/r32/esp
 4176     (tailor-exit-descriptor %edx 0x10)
 4177     #
 4178     (write _test-input-stream "fn foo {\n")
 4179     (write _test-input-stream "  var x: (array int 10)\n")
 4180     (write _test-input-stream "}\n")
 4181     # convert
 4182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4183     # registers except esp clobbered at this point
 4184     # restore ed
 4185     89/<- %edx 4/r32/esp
 4186     (flush _test-output-buffered-file)
 4187     (flush _test-error-buffered-file)
 4188 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4194     # check output
 4195     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 4196     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; either start '10' with a '0x' to be unambiguous, or convert it to decimal."  "F - test-array-size-in-hex: error message")
 4197     # check that stop(1) was called
 4198     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 4199     # don't restore from ebp
 4200     81 0/subop/add %esp 8/imm32
 4201     # . epilogue
 4202     5d/pop-to-ebp
 4203     c3/return
 4204 
 4205 test-convert-function-with-populate:
 4206     # . prologue
 4207     55/push-ebp
 4208     89/<- %ebp 4/r32/esp
 4209     # setup
 4210     (clear-stream _test-input-stream)
 4211     (clear-stream $_test-input-buffered-file->buffer)
 4212     (clear-stream _test-output-stream)
 4213     (clear-stream $_test-output-buffered-file->buffer)
 4214     #
 4215     (write _test-input-stream "fn foo {\n")
 4216     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 4217     (write _test-input-stream "  populate x, 7\n")
 4218     (write _test-input-stream "}\n")
 4219     # convert
 4220     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4221     (flush _test-output-buffered-file)
 4222 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4228     # check output
 4229     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 4230     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 4231     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 4232     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 4233     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 4234     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 4235     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 4236     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 4237     (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)
 4238     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 4239     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 4240     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 4241     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 4242     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 4243     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 4244     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 4245     # . epilogue
 4246     89/<- %esp 5/r32/ebp
 4247     5d/pop-to-ebp
 4248     c3/return
 4249 
 4250 # special-case for size(byte) when allocating array
 4251 test-convert-function-with-local-array-of-bytes-in-mem:
 4252     # . prologue
 4253     55/push-ebp
 4254     89/<- %ebp 4/r32/esp
 4255     # setup
 4256     (clear-stream _test-input-stream)
 4257     (clear-stream $_test-input-buffered-file->buffer)
 4258     (clear-stream _test-output-stream)
 4259     (clear-stream $_test-output-buffered-file->buffer)
 4260     #
 4261     (write _test-input-stream "fn foo {\n")
 4262     (write _test-input-stream "  var x: (array byte 3)\n")
 4263     (write _test-input-stream "}\n")
 4264     # convert
 4265     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4266     (flush _test-output-buffered-file)
 4267 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4273     # check output
 4274     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 4275     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 4276     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 4277     (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")
 4278     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 4279     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 4280     # define x
 4281     (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")
 4282     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 4283     # reclaim x
 4284     (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")
 4285     #
 4286     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 4287     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 4288     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 4289     (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")
 4290     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 4291     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 4292     # . epilogue
 4293     89/<- %esp 5/r32/ebp
 4294     5d/pop-to-ebp
 4295     c3/return
 4296 
 4297 test-convert-address:
 4298     # . prologue
 4299     55/push-ebp
 4300     89/<- %ebp 4/r32/esp
 4301     # setup
 4302     (clear-stream _test-input-stream)
 4303     (clear-stream $_test-input-buffered-file->buffer)
 4304     (clear-stream _test-output-stream)
 4305     (clear-stream $_test-output-buffered-file->buffer)
 4306     #
 4307     (write _test-input-stream "fn foo {\n")
 4308     (write _test-input-stream "  var a: int\n")
 4309     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 4310     (write _test-input-stream "}\n")
 4311     # convert
 4312     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4313     (flush _test-output-buffered-file)
 4314 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4320     # check output
 4321     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 4322     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 4323     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 4324     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 4325     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 4326     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 4327     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 4328     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 4329     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 4330     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 4331     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 4332     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 4333     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 4334     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 4335     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 4336     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 4337     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 4338     # . epilogue
 4339     89/<- %esp 5/r32/ebp
 4340     5d/pop-to-ebp
 4341     c3/return
 4342 
 4343 test-convert-floating-point-convert:
 4344     # . prologue
 4345     55/push-ebp
 4346     89/<- %ebp 4/r32/esp
 4347     # setup
 4348     (clear-stream _test-input-stream)
 4349     (clear-stream $_test-input-buffered-file->buffer)
 4350     (clear-stream _test-output-stream)
 4351     (clear-stream $_test-output-buffered-file->buffer)
 4352     #
 4353     (write _test-input-stream "fn foo {\n")
 4354     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4355     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4356     (write _test-input-stream "}\n")
 4357     # convert
 4358     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4359     (flush _test-output-buffered-file)
 4360 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4366     # check output
 4367     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 4368     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 4369     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 4370     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 4371     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 4372     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 4373     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 4374     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 4375     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 4376     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 4377     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 4378     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 4379     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-length-of-array-on-stack/12")
 4380     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 4381     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 4382     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 4383     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 4384     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 4385     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 4386     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 4387     # . epilogue
 4388     89/<- %esp 5/r32/ebp
 4389     5d/pop-to-ebp
 4390     c3/return
 4391 
 4392 test-convert-floating-point-convert-2:
 4393     # . prologue
 4394     55/push-ebp
 4395     89/<- %ebp 4/r32/esp
 4396     # setup
 4397     (clear-stream _test-input-stream)
 4398     (clear-stream $_test-input-buffered-file->buffer)
 4399     (clear-stream _test-output-stream)
 4400     (clear-stream $_test-output-buffered-file->buffer)
 4401     #
 4402     (write _test-input-stream "fn foo {\n")
 4403     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 4404     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 4405     (write _test-input-stream "  a <- convert b\n")
 4406     (write _test-input-stream "}\n")
 4407     # convert
 4408     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4409     (flush _test-output-buffered-file)
 4410 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4416     # check output
 4417     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 4418     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 4419     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 4420     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 4421     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 4422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 4423     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 4424     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 4425     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 4426     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 4427     (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")
 4428     (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")
 4429     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 4430     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-length-of-array-on-stack/13")
 4431     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 4432     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 4433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 4434     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 4435     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 4436     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 4437     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 4438     # . epilogue
 4439     89/<- %esp 5/r32/ebp
 4440     5d/pop-to-ebp
 4441     c3/return
 4442 
 4443 test-convert-floating-point-operation:
 4444     # . prologue
 4445     55/push-ebp
 4446     89/<- %ebp 4/r32/esp
 4447     # setup
 4448     (clear-stream _test-input-stream)
 4449     (clear-stream $_test-input-buffered-file->buffer)
 4450     (clear-stream _test-output-stream)
 4451     (clear-stream $_test-output-buffered-file->buffer)
 4452     #
 4453     (write _test-input-stream "fn f {\n")
 4454     (write _test-input-stream "  var m: float\n")
 4455     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 4456     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 4457     (write _test-input-stream "  x <- copy y\n")
 4458     (write _test-input-stream "  copy-to m, y\n")
 4459     (write _test-input-stream "  x <- add y\n")
 4460     (write _test-input-stream "  x <- add m\n")
 4461     (write _test-input-stream "  x <- subtract y\n")
 4462     (write _test-input-stream "  x <- subtract m\n")
 4463     (write _test-input-stream "  x <- multiply y\n")
 4464     (write _test-input-stream "  x <- multiply m\n")
 4465     (write _test-input-stream "  x <- divide y\n")
 4466     (write _test-input-stream "  x <- divide m\n")
 4467     (write _test-input-stream "  x <- reciprocal y\n")
 4468     (write _test-input-stream "  x <- reciprocal m\n")
 4469     (write _test-input-stream "  x <- square-root y\n")
 4470     (write _test-input-stream "  x <- square-root m\n")
 4471     (write _test-input-stream "  x <- inverse-square-root y\n")
 4472     (write _test-input-stream "  x <- inverse-square-root m\n")
 4473     (write _test-input-stream "  x <- max y\n")
 4474     (write _test-input-stream "  x <- max m\n")
 4475     (write _test-input-stream "  x <- min y\n")
 4476     (write _test-input-stream "  x <- min m\n")
 4477     (write _test-input-stream "  compare x, y\n")
 4478     (write _test-input-stream "  compare x, m\n")
 4479     (write _test-input-stream "}\n")
 4480     # convert
 4481     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4482     (flush _test-output-buffered-file)
 4483 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4489     # check output
 4490     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 4491     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 4492     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 4493     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 4494     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 4495     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 4496     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 4497     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 4498     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 4499     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 4500     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 4501     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 4502     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 4503     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 4504     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 4505     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 4506     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 4507     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 4508     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 4509     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 4510     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 4511     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 4512     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 4513     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 4514     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 4515     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 4516     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 4517     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 4518     (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")
 4519     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 4520     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 4521     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 4522     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 4523     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 4524     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 4525     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 4526     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 4527     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 4528     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 4529     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 4530     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 4531     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 4532     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 4533     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 4534     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 4535     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 4536     # . epilogue
 4537     89/<- %esp 5/r32/ebp
 4538     5d/pop-to-ebp
 4539     c3/return
 4540 
 4541 test-convert-floating-point-dereferenced:
 4542     # . prologue
 4543     55/push-ebp
 4544     89/<- %ebp 4/r32/esp
 4545     # setup
 4546     (clear-stream _test-input-stream)
 4547     (clear-stream $_test-input-buffered-file->buffer)
 4548     (clear-stream _test-output-stream)
 4549     (clear-stream $_test-output-buffered-file->buffer)
 4550     #
 4551     (write _test-input-stream "fn f {\n")
 4552     (write _test-input-stream "  var m: float\n")
 4553     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 4554     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 4555     (write _test-input-stream "  x <- multiply *y\n")
 4556     (write _test-input-stream "}\n")
 4557     # convert
 4558     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4559     (flush _test-output-buffered-file)
 4560 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4566     # check output
 4567     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 4568     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 4569     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 4570     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 4571     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 4572     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 4573     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 4574     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 4575     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 4576     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 4577     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 4578     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 4579     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 4580     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 4581     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 4582     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 4583     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 4584     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 4585     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 4586     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 4587     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 4588     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 4589     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 4590     # . epilogue
 4591     89/<- %esp 5/r32/ebp
 4592     5d/pop-to-ebp
 4593     c3/return
 4594 
 4595 test-convert-length-of-array:
 4596     # . prologue
 4597     55/push-ebp
 4598     89/<- %ebp 4/r32/esp
 4599     # setup
 4600     (clear-stream _test-input-stream)
 4601     (clear-stream $_test-input-buffered-file->buffer)
 4602     (clear-stream _test-output-stream)
 4603     (clear-stream $_test-output-buffered-file->buffer)
 4604     #
 4605     (write _test-input-stream "fn foo a: (addr array int) {\n")
 4606     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 4607     (write _test-input-stream "  var c/eax: int <- length b\n")
 4608     (write _test-input-stream "}\n")
 4609     # convert
 4610     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4611     (flush _test-output-buffered-file)
 4612 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4618     # check output
 4619     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 4620     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 4621     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 4622     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 4623     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 4624     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 4625     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 4626     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 4627     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 4628     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 4629     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 4630     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 4631     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 4632     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 4633     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 4634     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 4635     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 4636     # . epilogue
 4637     89/<- %esp 5/r32/ebp
 4638     5d/pop-to-ebp
 4639     c3/return
 4640 
 4641 # special-case for size(byte) when computing array length
 4642 test-convert-length-of-array-of-bytes:
 4643     # . prologue
 4644     55/push-ebp
 4645     89/<- %ebp 4/r32/esp
 4646     # setup
 4647     (clear-stream _test-input-stream)
 4648     (clear-stream $_test-input-buffered-file->buffer)
 4649     (clear-stream _test-output-stream)
 4650     (clear-stream $_test-output-buffered-file->buffer)
 4651     #
 4652     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 4653     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 4654     (write _test-input-stream "  var c/eax: int <- length b\n")
 4655     (write _test-input-stream "}\n")
 4656     # convert
 4657     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4658     (flush _test-output-buffered-file)
 4659 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4665     # check output
 4666     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 4667     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 4668     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 4669     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 4670     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 4671     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 4672     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 4673     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 4674     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 4675     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 4676     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 4677     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 4678     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 4679     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 4680     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 4681     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 4682     # . epilogue
 4683     89/<- %esp 5/r32/ebp
 4684     5d/pop-to-ebp
 4685     c3/return
 4686 
 4687 test-convert-length-of-array-on-stack:
 4688     # . prologue
 4689     55/push-ebp
 4690     89/<- %ebp 4/r32/esp
 4691     # setup
 4692     (clear-stream _test-input-stream)
 4693     (clear-stream $_test-input-buffered-file->buffer)
 4694     (clear-stream _test-output-stream)
 4695     (clear-stream $_test-output-buffered-file->buffer)
 4696     #
 4697     (write _test-input-stream "fn foo {\n")
 4698     (write _test-input-stream "  var a: (array int 3)\n")
 4699     (write _test-input-stream "  var b/eax: int <- length a\n")
 4700     (write _test-input-stream "}\n")
 4701     # convert
 4702     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4703     (flush _test-output-buffered-file)
 4704 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4710     # check output
 4711     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 4712     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 4713     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 4714     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 4715     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 4716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 4717     # define x
 4718     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 4719     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 4720     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 4721     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 4722     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 4723     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 4724     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 4725     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 4726     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 4727     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 4728     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 4729     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 4730     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 4731     # . epilogue
 4732     89/<- %esp 5/r32/ebp
 4733     5d/pop-to-ebp
 4734     c3/return
 4735 
 4736 test-reg-var-def-with-read-of-same-register:
 4737     # . prologue
 4738     55/push-ebp
 4739     89/<- %ebp 4/r32/esp
 4740     # setup
 4741     (clear-stream _test-input-stream)
 4742     (clear-stream $_test-input-buffered-file->buffer)
 4743     (clear-stream _test-output-stream)
 4744     (clear-stream $_test-output-buffered-file->buffer)
 4745     (clear-stream _test-error-stream)
 4746     (clear-stream $_test-error-buffered-file->buffer)
 4747     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 4748     68/push 0/imm32
 4749     68/push 0/imm32
 4750     89/<- %edx 4/r32/esp
 4751     (tailor-exit-descriptor %edx 0x10)
 4752     #
 4753     (write _test-input-stream "fn foo {\n")
 4754     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4755     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4756     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4757     (write _test-input-stream "}\n")
 4758     # convert
 4759     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4760     # registers except esp could be clobbered at this point (though they shouldn't be)
 4761     # restore ed
 4762     89/<- %edx 4/r32/esp
 4763     (flush _test-output-buffered-file)
 4764     (flush _test-error-buffered-file)
 4765 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4771 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 4777     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 4778     # check output
 4779     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 4780     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 4781     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 4782     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 4783     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 4784     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 4785     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 4786     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 4787     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-reg-var-def-with-read-of-same-register/8")
 4788     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/9")
 4789     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-reg-var-def-with-read-of-same-register/11")
 4790     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-reg-var-def-with-read-of-same-register/13")
 4791     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/14")
 4792     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/15")
 4793     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/16")
 4794     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/17")
 4795     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/18")
 4796     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/19")
 4797     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/20")
 4798     # don't restore from ebp
 4799     81 0/subop/add %esp 8/imm32
 4800     # . epilogue
 4801     5d/pop-to-ebp
 4802     c3/return
 4803 
 4804 test-convert-index-into-array:
 4805     # . prologue
 4806     55/push-ebp
 4807     89/<- %ebp 4/r32/esp
 4808     # setup
 4809     (clear-stream _test-input-stream)
 4810     (clear-stream $_test-input-buffered-file->buffer)
 4811     (clear-stream _test-output-stream)
 4812     (clear-stream $_test-output-buffered-file->buffer)
 4813     #
 4814     (write _test-input-stream "fn foo {\n")
 4815     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4816     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4817     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 4818     (write _test-input-stream "}\n")
 4819     # convert
 4820     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4821     (flush _test-output-buffered-file)
 4822 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4828     # check output
 4829     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 4830     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 4831     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 4832     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 4833     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 4834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 4835     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 4836     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 4837     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 4838     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 4839     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/10")
 4840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/11")
 4841     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/12")
 4842     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/13")
 4843     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/14")
 4844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/15")
 4845     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/16")
 4846     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/17")
 4847     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/18")
 4848     # . epilogue
 4849     89/<- %esp 5/r32/ebp
 4850     5d/pop-to-ebp
 4851     c3/return
 4852 
 4853 test-convert-index-into-array-of-bytes:
 4854     # . prologue
 4855     55/push-ebp
 4856     89/<- %ebp 4/r32/esp
 4857     # setup
 4858     (clear-stream _test-input-stream)
 4859     (clear-stream $_test-input-buffered-file->buffer)
 4860     (clear-stream _test-output-stream)
 4861     (clear-stream $_test-output-buffered-file->buffer)
 4862     #
 4863     (write _test-input-stream "fn foo {\n")
 4864     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4865     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 4866     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 4867     (write _test-input-stream "}\n")
 4868     # convert
 4869     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4870     (flush _test-output-buffered-file)
 4871 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4877     # check output
 4878     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 4879     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 4880     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 4881     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 4882     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 4883     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 4884     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 4885     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 4886     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 4887     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 4888     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/11")
 4889     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/13")
 4890     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/14")
 4891     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/15")
 4892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/16")
 4893     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/17")
 4894     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/18")
 4895     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/19")
 4896     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/20")
 4897     # . epilogue
 4898     89/<- %esp 5/r32/ebp
 4899     5d/pop-to-ebp
 4900     c3/return
 4901 
 4902 test-convert-index-into-array-with-literal:
 4903     # . prologue
 4904     55/push-ebp
 4905     89/<- %ebp 4/r32/esp
 4906     # setup
 4907     (clear-stream _test-input-stream)
 4908     (clear-stream $_test-input-buffered-file->buffer)
 4909     (clear-stream _test-output-stream)
 4910     (clear-stream $_test-output-buffered-file->buffer)
 4911     #
 4912     (write _test-input-stream "fn foo {\n")
 4913     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 4914     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 4915     (write _test-input-stream "}\n")
 4916     # convert
 4917     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4918     (flush _test-output-buffered-file)
 4919 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4925     # check output
 4926     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 4927     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 4928     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 4929     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 4930     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 4931     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 4932     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 4933     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 4934                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 4935     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/8")
 4936     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/9")
 4937     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/10")
 4938     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/11")
 4939     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/12")
 4940     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/13")
 4941     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/14")
 4942     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/15")
 4943     # . epilogue
 4944     89/<- %esp 5/r32/ebp
 4945     5d/pop-to-ebp
 4946     c3/return
 4947 
 4948 test-convert-index-into-array-of-bytes-with-literal:
 4949     # . prologue
 4950     55/push-ebp
 4951     89/<- %ebp 4/r32/esp
 4952     # setup
 4953     (clear-stream _test-input-stream)
 4954     (clear-stream $_test-input-buffered-file->buffer)
 4955     (clear-stream _test-output-stream)
 4956     (clear-stream $_test-output-buffered-file->buffer)
 4957     #
 4958     (write _test-input-stream "fn foo {\n")
 4959     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 4960     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 4961     (write _test-input-stream "}\n")
 4962     # convert
 4963     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4964     (flush _test-output-buffered-file)
 4965 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 4971     # check output
 4972     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 4973     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 4974     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 4975     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 4976     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 4977     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 4978     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 4979     (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")
 4980                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 4981     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 4982     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 4983     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 4984     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 4985     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 4986     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 4987     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 4988     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 4989     # . epilogue
 4990     89/<- %esp 5/r32/ebp
 4991     5d/pop-to-ebp
 4992     c3/return
 4993 
 4994 test-convert-index-into-array-on-stack:
 4995     # . prologue
 4996     55/push-ebp
 4997     89/<- %ebp 4/r32/esp
 4998     # setup
 4999     (clear-stream _test-input-stream)
 5000     (clear-stream $_test-input-buffered-file->buffer)
 5001     (clear-stream _test-output-stream)
 5002     (clear-stream $_test-output-buffered-file->buffer)
 5003     #
 5004     (write _test-input-stream "fn foo {\n")
 5005     (write _test-input-stream "  var arr: (array int 3)\n")
 5006     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 5007     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5008     (write _test-input-stream "}\n")
 5009     # convert
 5010     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5011     (flush _test-output-buffered-file)
 5012 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5018     # check output
 5019     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 5020     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 5021     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 5022     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 5023     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 5024     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 5025     # var arr
 5026     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 5027     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 5028     # var idx
 5029     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 5030     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 5031     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 5032     (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/10")
 5033     # reclaim idx
 5034     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/11")
 5035     # reclaim arr
 5036     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/12")
 5037     #
 5038     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/13")
 5039     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/14")
 5040     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/15")
 5041     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/16")
 5042     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/17")
 5043     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/18")
 5044     # . epilogue
 5045     89/<- %esp 5/r32/ebp
 5046     5d/pop-to-ebp
 5047     c3/return
 5048 
 5049 test-convert-index-into-array-on-stack-with-literal:
 5050     # . prologue
 5051     55/push-ebp
 5052     89/<- %ebp 4/r32/esp
 5053     # setup
 5054     (clear-stream _test-input-stream)
 5055     (clear-stream $_test-input-buffered-file->buffer)
 5056     (clear-stream _test-output-stream)
 5057     (clear-stream $_test-output-buffered-file->buffer)
 5058     #
 5059     (write _test-input-stream "fn foo {\n")
 5060     (write _test-input-stream "  var arr: (array int 3)\n")
 5061     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 5062     (write _test-input-stream "}\n")
 5063     # convert
 5064     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5065     (flush _test-output-buffered-file)
 5066 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5072     # check output
 5073     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 5074     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 5075     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 5076     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 5077     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 5078     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 5079     # var arr
 5080     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 5081     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 5082     # var x
 5083     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 5084     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 5085     (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/9")
 5086     # reclaim x
 5087     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/10")
 5088     # reclaim arr
 5089     (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/11")
 5090     #
 5091     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/12")
 5092     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/13")
 5093     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/14")
 5094     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/15")
 5095     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/16")
 5096     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/17")
 5097     # . epilogue
 5098     89/<- %esp 5/r32/ebp
 5099     5d/pop-to-ebp
 5100     c3/return
 5101 
 5102 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 5103     # . prologue
 5104     55/push-ebp
 5105     89/<- %ebp 4/r32/esp
 5106     # setup
 5107     (clear-stream _test-input-stream)
 5108     (clear-stream $_test-input-buffered-file->buffer)
 5109     (clear-stream _test-output-stream)
 5110     (clear-stream $_test-output-buffered-file->buffer)
 5111     #
 5112     (write _test-input-stream "fn foo {\n")
 5113     (write _test-input-stream "  var arr: (array byte 3)\n")
 5114     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 5115     (write _test-input-stream "}\n")
 5116     # convert
 5117     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5118     (flush _test-output-buffered-file)
 5119 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5125     # check output
 5126     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 5127     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 5128     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 5129     (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")
 5130     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 5131     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 5132     # var arr
 5133     (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")
 5134     (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")
 5135     # var x
 5136     (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")
 5137     # x is at (ebp-7) + 4 + 2 = ebp-1
 5138     (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/9")
 5139     # reclaim x
 5140     (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/10")
 5141     # reclaim arr
 5142     (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/11")
 5143     #
 5144     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 5145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 5146     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 5147     (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/15")
 5148     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 5149     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 5150     # . epilogue
 5151     89/<- %esp 5/r32/ebp
 5152     5d/pop-to-ebp
 5153     c3/return
 5154 
 5155 test-convert-index-into-array-using-offset:
 5156     # . prologue
 5157     55/push-ebp
 5158     89/<- %ebp 4/r32/esp
 5159     # setup
 5160     (clear-stream _test-input-stream)
 5161     (clear-stream $_test-input-buffered-file->buffer)
 5162     (clear-stream _test-output-stream)
 5163     (clear-stream $_test-output-buffered-file->buffer)
 5164     #
 5165     (write _test-input-stream "fn foo {\n")
 5166     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5167     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5168     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5169     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5170     (write _test-input-stream "}\n")
 5171     # convert
 5172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5173     (flush _test-output-buffered-file)
 5174 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5180     # check output
 5181     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 5182     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 5183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 5184     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 5185     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 5186     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 5187     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 5188     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 5189     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 5190     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 5191     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 5192     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/11")
 5193     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/12")
 5194     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/13")
 5195     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/14")
 5196     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/15")
 5197     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/16")
 5198     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/17")
 5199     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/18")
 5200     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/19")
 5201     # . epilogue
 5202     89/<- %esp 5/r32/ebp
 5203     5d/pop-to-ebp
 5204     c3/return
 5205 
 5206 test-convert-index-into-array-of-bytes-using-offset:
 5207     # . prologue
 5208     55/push-ebp
 5209     89/<- %ebp 4/r32/esp
 5210     # setup
 5211     (clear-stream _test-input-stream)
 5212     (clear-stream $_test-input-buffered-file->buffer)
 5213     (clear-stream _test-output-stream)
 5214     (clear-stream $_test-output-buffered-file->buffer)
 5215     #
 5216     (write _test-input-stream "fn foo {\n")
 5217     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5218     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5219     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5220     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5221     (write _test-input-stream "}\n")
 5222     # convert
 5223     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5224     (flush _test-output-buffered-file)
 5225 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5231     # check output
 5232     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 5233     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 5234     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 5235     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 5236     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 5237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 5238     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 5239     (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")
 5240     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 5241     (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")
 5242     (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")
 5243     (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/11")
 5244     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/12")
 5245     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 5246     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/14")
 5247     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/15")
 5248     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/16")
 5249     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/17")
 5250     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/18")
 5251     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/19")
 5252     # . epilogue
 5253     89/<- %esp 5/r32/ebp
 5254     5d/pop-to-ebp
 5255     c3/return
 5256 
 5257 test-convert-index-into-array-using-offset-on-stack:
 5258     # . prologue
 5259     55/push-ebp
 5260     89/<- %ebp 4/r32/esp
 5261     # setup
 5262     (clear-stream _test-input-stream)
 5263     (clear-stream $_test-input-buffered-file->buffer)
 5264     (clear-stream _test-output-stream)
 5265     (clear-stream $_test-output-buffered-file->buffer)
 5266     #
 5267     (write _test-input-stream "fn foo {\n")
 5268     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5269     (write _test-input-stream "  var idx: int\n")
 5270     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 5271     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 5272     (write _test-input-stream "}\n")
 5273     # convert
 5274     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5275     (flush _test-output-buffered-file)
 5276 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5282     # check output
 5283     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 5284     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 5285     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 5286     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 5287     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 5288     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 5289     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 5290     (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")
 5291     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 5292     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 5293     (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")
 5294     (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/11")
 5295     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/12")
 5296     (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/13")
 5297     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/14")
 5298     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/15")
 5299     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/16")
 5300     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/17")
 5301     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/18")
 5302     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/19")
 5303     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/20")
 5304     # . epilogue
 5305     89/<- %esp 5/r32/ebp
 5306     5d/pop-to-ebp
 5307     c3/return
 5308 
 5309 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 5310     # . prologue
 5311     55/push-ebp
 5312     89/<- %ebp 4/r32/esp
 5313     # setup
 5314     (clear-stream _test-input-stream)
 5315     (clear-stream $_test-input-buffered-file->buffer)
 5316     (clear-stream _test-output-stream)
 5317     (clear-stream $_test-output-buffered-file->buffer)
 5318     #
 5319     (write _test-input-stream "fn foo {\n")
 5320     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 5321     (write _test-input-stream "  var idx: int\n")
 5322     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 5323     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 5324     (write _test-input-stream "}\n")
 5325     # convert
 5326     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5327     (flush _test-output-buffered-file)
 5328 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5334     # check output
 5335     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 5336     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 5337     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 5338     (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")
 5339     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 5340     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 5341     (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")
 5342     (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")
 5343     (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")
 5344     (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")
 5345     (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")
 5346     (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/11")
 5347     (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/12")
 5348     (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/13")
 5349     (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/14")
 5350     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 5351     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 5352     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 5353     (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/18")
 5354     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 5355     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 5356     # . epilogue
 5357     89/<- %esp 5/r32/ebp
 5358     5d/pop-to-ebp
 5359     c3/return
 5360 
 5361 test-convert-function-and-type-definition:
 5362     # . prologue
 5363     55/push-ebp
 5364     89/<- %ebp 4/r32/esp
 5365     # setup
 5366     (clear-stream _test-input-stream)
 5367     (clear-stream $_test-input-buffered-file->buffer)
 5368     (clear-stream _test-output-stream)
 5369     (clear-stream $_test-output-buffered-file->buffer)
 5370     #
 5371     (write _test-input-stream "fn foo a: (addr t) {\n")
 5372     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 5373     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 5374     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 5375     (write _test-input-stream "}\n")
 5376     (write _test-input-stream "type t {\n")
 5377     (write _test-input-stream "  x: int\n")
 5378     (write _test-input-stream "  y: int\n")
 5379     (write _test-input-stream "}\n")
 5380     # convert
 5381     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5382     (flush _test-output-buffered-file)
 5383 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5389     # check output
 5390     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 5391     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 5392     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 5393     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 5394     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 5395     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 5396     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 5397     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 5398     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 5399     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 5400     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 5401     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 5402     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 5403     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 5404     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 5405     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 5406     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 5407     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 5408     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 5409     # . epilogue
 5410     89/<- %esp 5/r32/ebp
 5411     5d/pop-to-ebp
 5412     c3/return
 5413 
 5414 test-type-definition-with-array:
 5415     # . prologue
 5416     55/push-ebp
 5417     89/<- %ebp 4/r32/esp
 5418     # setup
 5419     (clear-stream _test-input-stream)
 5420     (clear-stream $_test-input-buffered-file->buffer)
 5421     (clear-stream _test-output-stream)
 5422     (clear-stream $_test-output-buffered-file->buffer)
 5423     (clear-stream _test-error-stream)
 5424     (clear-stream $_test-error-buffered-file->buffer)
 5425     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5426     68/push 0/imm32
 5427     68/push 0/imm32
 5428     89/<- %edx 4/r32/esp
 5429     (tailor-exit-descriptor %edx 0x10)
 5430     #
 5431     (write _test-input-stream "type t {\n")
 5432     (write _test-input-stream "  a: (array int 3)\n")
 5433     (write _test-input-stream "}\n")
 5434     # convert
 5435     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5436     # registers except esp clobbered at this point
 5437     # restore ed
 5438     89/<- %edx 4/r32/esp
 5439     (flush _test-output-buffered-file)
 5440     (flush _test-error-buffered-file)
 5441 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5447     # check output
 5448     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 5449     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 5450     # check that stop(1) was called
 5451     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 5452     # don't restore from ebp
 5453     81 0/subop/add %esp 8/imm32
 5454     # . epilogue
 5455     5d/pop-to-ebp
 5456     c3/return
 5457 
 5458 test-type-definition-with-addr:
 5459     # . prologue
 5460     55/push-ebp
 5461     89/<- %ebp 4/r32/esp
 5462     # setup
 5463     (clear-stream _test-input-stream)
 5464     (clear-stream $_test-input-buffered-file->buffer)
 5465     (clear-stream _test-output-stream)
 5466     (clear-stream $_test-output-buffered-file->buffer)
 5467     (clear-stream _test-error-stream)
 5468     (clear-stream $_test-error-buffered-file->buffer)
 5469     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5470     68/push 0/imm32
 5471     68/push 0/imm32
 5472     89/<- %edx 4/r32/esp
 5473     (tailor-exit-descriptor %edx 0x10)
 5474     #
 5475     (write _test-input-stream "type t {\n")
 5476     (write _test-input-stream "  a: (addr int)\n")
 5477     (write _test-input-stream "}\n")
 5478     # convert
 5479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5480     # registers except esp clobbered at this point
 5481     # restore ed
 5482     89/<- %edx 4/r32/esp
 5483     (flush _test-output-buffered-file)
 5484     (flush _test-error-buffered-file)
 5485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5491     # check output
 5492     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 5493     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 5494     # check that stop(1) was called
 5495     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 5496     # don't restore from ebp
 5497     81 0/subop/add %esp 8/imm32
 5498     # . epilogue
 5499     5d/pop-to-ebp
 5500     c3/return
 5501 
 5502 test-convert-function-with-local-var-with-user-defined-type:
 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 "  var a: t\n")
 5514     (write _test-input-stream "}\n")
 5515     (write _test-input-stream "type t {\n")
 5516     (write _test-input-stream "  x: int\n")
 5517     (write _test-input-stream "  y: int\n")
 5518     (write _test-input-stream "}\n")
 5519     # convert
 5520     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5521     (flush _test-output-buffered-file)
 5522 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5528     # check output
 5529     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 5530     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 5531     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 5532     (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")
 5533     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 5534     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 5535     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 5536     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 5537     (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")
 5538     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 5539     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 5540     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 5541     (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")
 5542     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 5543     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 5544     # . epilogue
 5545     89/<- %esp 5/r32/ebp
 5546     5d/pop-to-ebp
 5547     c3/return
 5548 
 5549 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 5550     # . prologue
 5551     55/push-ebp
 5552     89/<- %ebp 4/r32/esp
 5553     # setup
 5554     (clear-stream _test-input-stream)
 5555     (clear-stream $_test-input-buffered-file->buffer)
 5556     (clear-stream _test-output-stream)
 5557     (clear-stream $_test-output-buffered-file->buffer)
 5558     #
 5559     (write _test-input-stream "fn foo {\n")
 5560     (write _test-input-stream "  var a: t\n")
 5561     (write _test-input-stream "}\n")
 5562     (write _test-input-stream "type t {\n")
 5563     (write _test-input-stream "  x: s\n")
 5564     (write _test-input-stream "}\n")
 5565     (write _test-input-stream "type s {\n")
 5566     (write _test-input-stream "  z: int\n")
 5567     (write _test-input-stream "}\n")
 5568     # convert
 5569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5570     (flush _test-output-buffered-file)
 5571 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5577     # check output
 5578     (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")
 5579     (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")
 5580     (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")
 5581     (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")
 5582     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 5583     (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")
 5584     (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")
 5585     (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")
 5586     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 5587     (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")
 5588     (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")
 5589     (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")
 5590     (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")
 5591     (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")
 5592     # . epilogue
 5593     89/<- %esp 5/r32/ebp
 5594     5d/pop-to-ebp
 5595     c3/return
 5596 
 5597 test-convert-function-call-with-arg-of-user-defined-type:
 5598     # . prologue
 5599     55/push-ebp
 5600     89/<- %ebp 4/r32/esp
 5601     # setup
 5602     (clear-stream _test-input-stream)
 5603     (clear-stream $_test-input-buffered-file->buffer)
 5604     (clear-stream _test-output-stream)
 5605     (clear-stream $_test-output-buffered-file->buffer)
 5606     #
 5607     (write _test-input-stream "fn f {\n")
 5608     (write _test-input-stream "  var a: t\n")
 5609     (write _test-input-stream "  foo a\n")
 5610     (write _test-input-stream "}\n")
 5611     (write _test-input-stream "fn foo x: t {\n")
 5612     (write _test-input-stream "}\n")
 5613     (write _test-input-stream "type t {\n")
 5614     (write _test-input-stream "  x: int\n")
 5615     (write _test-input-stream "  y: int\n")
 5616     (write _test-input-stream "}\n")
 5617     # convert
 5618     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5619     (flush _test-output-buffered-file)
 5620 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5626     # check output
 5627     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5628     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5629     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 5630     (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")
 5631     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 5632     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 5633     # var a: t
 5634     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 5635     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 5636     # foo a
 5637     (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")
 5638     #
 5639     (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")
 5640     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 5641     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 5642     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 5643     (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")
 5644     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 5645     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 5646     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 5647     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 5648     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 5649     (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")
 5650     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 5651     (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")
 5652     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 5653     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 5654     # . epilogue
 5655     89/<- %esp 5/r32/ebp
 5656     5d/pop-to-ebp
 5657     c3/return
 5658 
 5659 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 5660     # . prologue
 5661     55/push-ebp
 5662     89/<- %ebp 4/r32/esp
 5663     # setup
 5664     (clear-stream _test-input-stream)
 5665     (clear-stream $_test-input-buffered-file->buffer)
 5666     (clear-stream _test-output-stream)
 5667     (clear-stream $_test-output-buffered-file->buffer)
 5668     #
 5669     (write _test-input-stream "fn f {\n")
 5670     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 5671     (write _test-input-stream "  foo *a\n")
 5672     (write _test-input-stream "}\n")
 5673     (write _test-input-stream "fn foo x: t {\n")
 5674     (write _test-input-stream "}\n")
 5675     (write _test-input-stream "type t {\n")
 5676     (write _test-input-stream "  x: int\n")
 5677     (write _test-input-stream "  y: int\n")
 5678     (write _test-input-stream "}\n")
 5679     # convert
 5680     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5681     (flush _test-output-buffered-file)
 5682 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5688     # check output
 5689     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 5690     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 5691     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 5692     (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")
 5693     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 5694     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 5695     # var a
 5696     (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")
 5697     (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")
 5698     # foo a
 5699     (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")
 5700     #
 5701     (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")
 5702     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 5703     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 5704     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 5705     (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")
 5706     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 5707     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 5708     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 5709     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 5710     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 5711     (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")
 5712     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 5713     (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")
 5714     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 5715     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 5716     # . epilogue
 5717     89/<- %esp 5/r32/ebp
 5718     5d/pop-to-ebp
 5719     c3/return
 5720 
 5721 # we don't have special support for call-by-reference; just explicitly create
 5722 # a new variable with the address of the arg
 5723 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 5724     # . prologue
 5725     55/push-ebp
 5726     89/<- %ebp 4/r32/esp
 5727     # setup
 5728     (clear-stream _test-input-stream)
 5729     (clear-stream $_test-input-buffered-file->buffer)
 5730     (clear-stream _test-output-stream)
 5731     (clear-stream $_test-output-buffered-file->buffer)
 5732     #
 5733     (write _test-input-stream "fn f {\n")
 5734     (write _test-input-stream "  var a: t\n")
 5735     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 5736     (write _test-input-stream "  foo b\n")
 5737     (write _test-input-stream "}\n")
 5738     (write _test-input-stream "fn foo x: (addr t) {\n")
 5739     (write _test-input-stream "  var x/ecx: (addr int) <- copy x\n")
 5740     (write _test-input-stream "  increment *x\n")
 5741     (write _test-input-stream "}\n")
 5742     (write _test-input-stream "type t {\n")
 5743     (write _test-input-stream "  x: int\n")
 5744     (write _test-input-stream "  y: int\n")
 5745     (write _test-input-stream "}\n")
 5746     # convert
 5747     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5748     (flush _test-output-buffered-file)
 5749 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5755     # check output
 5756     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 5757     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 5758     (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")
 5759     (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")
 5760     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 5761     (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")
 5762     # var a: t
 5763     (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")
 5764     (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")
 5765     # var b/eax: (addr t)
 5766     (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")
 5767     (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")
 5768     # foo a
 5769     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 5770     #
 5771     (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")
 5772     (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")
 5773     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 5774     (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")
 5775     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 5776     (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")
 5777     (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")
 5778     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 5779     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 5780     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 5781     (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")
 5782     (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")
 5783     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 5784     (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")
 5785     (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")
 5786     (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")
 5787     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 5788     (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/28")
 5789     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 5790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 5791     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 5792     (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/32")
 5793     (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/33")
 5794     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/34")
 5795     # . epilogue
 5796     89/<- %esp 5/r32/ebp
 5797     5d/pop-to-ebp
 5798     c3/return
 5799 
 5800 test-convert-get-on-local-variable:
 5801     # . prologue
 5802     55/push-ebp
 5803     89/<- %ebp 4/r32/esp
 5804     # setup
 5805     (clear-stream _test-input-stream)
 5806     (clear-stream $_test-input-buffered-file->buffer)
 5807     (clear-stream _test-output-stream)
 5808     (clear-stream $_test-output-buffered-file->buffer)
 5809     #
 5810     (write _test-input-stream "fn foo {\n")
 5811     (write _test-input-stream "  var a: t\n")
 5812     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5813     (write _test-input-stream "}\n")
 5814     (write _test-input-stream "type t {\n")
 5815     (write _test-input-stream "  x: int\n")
 5816     (write _test-input-stream "  y: int\n")
 5817     (write _test-input-stream "}\n")
 5818     # convert
 5819     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5820     (flush _test-output-buffered-file)
 5821 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5827     # check output
 5828     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 5829     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 5830     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 5831     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 5832     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 5833     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 5834     # var a
 5835     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 5836     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 5837     # var c
 5838     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 5839     # get
 5840     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 5841     # reclaim c
 5842     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 5843     # reclaim a
 5844     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 5845     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 5846     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 5847     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 5848     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 5849     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 5850     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 5851     # . epilogue
 5852     89/<- %esp 5/r32/ebp
 5853     5d/pop-to-ebp
 5854     c3/return
 5855 
 5856 test-convert-get-on-function-argument:
 5857     # . prologue
 5858     55/push-ebp
 5859     89/<- %ebp 4/r32/esp
 5860     # setup
 5861     (clear-stream _test-input-stream)
 5862     (clear-stream $_test-input-buffered-file->buffer)
 5863     (clear-stream _test-output-stream)
 5864     (clear-stream $_test-output-buffered-file->buffer)
 5865     #
 5866     (write _test-input-stream "fn foo a: t {\n")
 5867     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5868     (write _test-input-stream "}\n")
 5869     (write _test-input-stream "type t {\n")
 5870     (write _test-input-stream "  x: int\n")
 5871     (write _test-input-stream "  y: int\n")
 5872     (write _test-input-stream "}\n")
 5873     # convert
 5874     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5875     (flush _test-output-buffered-file)
 5876 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5882     # check output
 5883     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 5884     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 5885     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 5886     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 5887     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 5888     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 5889     # var c
 5890     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 5891     # get
 5892     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 5893     # reclaim c
 5894     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 5895     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 5896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 5897     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 5898     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 5899     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 5900     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 5901     # . epilogue
 5902     89/<- %esp 5/r32/ebp
 5903     5d/pop-to-ebp
 5904     c3/return
 5905 
 5906 test-convert-get-on-function-argument-with-known-type:
 5907     # . prologue
 5908     55/push-ebp
 5909     89/<- %ebp 4/r32/esp
 5910     # setup
 5911     (clear-stream _test-input-stream)
 5912     (clear-stream $_test-input-buffered-file->buffer)
 5913     (clear-stream _test-output-stream)
 5914     (clear-stream $_test-output-buffered-file->buffer)
 5915     #
 5916     (write _test-input-stream "type t {\n")
 5917     (write _test-input-stream "  x: int\n")
 5918     (write _test-input-stream "  y: int\n")
 5919     (write _test-input-stream "}\n")
 5920     (write _test-input-stream "fn foo a: t {\n")
 5921     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 5922     (write _test-input-stream "}\n")
 5923     # convert
 5924     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5925     (flush _test-output-buffered-file)
 5926 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 5932     # check output
 5933     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 5934     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 5935     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 5936     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 5937     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 5938     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 5939     # var c
 5940     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 5941     # get
 5942     (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")
 5943     # reclaim c
 5944     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 5945     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 5946     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 5947     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 5948     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 5949     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 5950     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 5951     # . epilogue
 5952     89/<- %esp 5/r32/ebp
 5953     5d/pop-to-ebp
 5954     c3/return
 5955 
 5956 test-add-with-too-many-inouts:
 5957     # . prologue
 5958     55/push-ebp
 5959     89/<- %ebp 4/r32/esp
 5960     # setup
 5961     (clear-stream _test-input-stream)
 5962     (clear-stream $_test-input-buffered-file->buffer)
 5963     (clear-stream _test-output-stream)
 5964     (clear-stream $_test-output-buffered-file->buffer)
 5965     (clear-stream _test-error-stream)
 5966     (clear-stream $_test-error-buffered-file->buffer)
 5967     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5968     68/push 0/imm32
 5969     68/push 0/imm32
 5970     89/<- %edx 4/r32/esp
 5971     (tailor-exit-descriptor %edx 0x10)
 5972     #
 5973     (write _test-input-stream "fn foo {\n")
 5974     (write _test-input-stream "  var a: int\n")
 5975     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 5976     (write _test-input-stream "}\n")
 5977     # convert
 5978     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5979     # registers except esp clobbered at this point
 5980     # restore ed
 5981     89/<- %edx 4/r32/esp
 5982     (flush _test-output-buffered-file)
 5983     (flush _test-error-buffered-file)
 5984 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 5990     # check output
 5991     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 5992     (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")
 5993     # check that stop(1) was called
 5994     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 5995     # don't restore from ebp
 5996     81 0/subop/add %esp 8/imm32
 5997     # . epilogue
 5998     5d/pop-to-ebp
 5999     c3/return
 6000 
 6001 test-add-with-too-many-inouts-2:
 6002     # . prologue
 6003     55/push-ebp
 6004     89/<- %ebp 4/r32/esp
 6005     # setup
 6006     (clear-stream _test-input-stream)
 6007     (clear-stream $_test-input-buffered-file->buffer)
 6008     (clear-stream _test-output-stream)
 6009     (clear-stream $_test-output-buffered-file->buffer)
 6010     (clear-stream _test-error-stream)
 6011     (clear-stream $_test-error-buffered-file->buffer)
 6012     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6013     68/push 0/imm32
 6014     68/push 0/imm32
 6015     89/<- %edx 4/r32/esp
 6016     (tailor-exit-descriptor %edx 0x10)
 6017     #
 6018     (write _test-input-stream "fn foo {\n")
 6019     (write _test-input-stream "  var a: int\n")
 6020     (write _test-input-stream "  add-to a, 0, 1\n")
 6021     (write _test-input-stream "}\n")
 6022     # convert
 6023     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6024     # registers except esp clobbered at this point
 6025     # restore ed
 6026     89/<- %edx 4/r32/esp
 6027     (flush _test-output-buffered-file)
 6028     (flush _test-error-buffered-file)
 6029 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6035     # check output
 6036     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 6037     (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")
 6038     # check that stop(1) was called
 6039     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 6040     # don't restore from ebp
 6041     81 0/subop/add %esp 8/imm32
 6042     # . epilogue
 6043     5d/pop-to-ebp
 6044     c3/return
 6045 
 6046 test-add-with-too-many-outputs:
 6047     # . prologue
 6048     55/push-ebp
 6049     89/<- %ebp 4/r32/esp
 6050     # setup
 6051     (clear-stream _test-input-stream)
 6052     (clear-stream $_test-input-buffered-file->buffer)
 6053     (clear-stream _test-output-stream)
 6054     (clear-stream $_test-output-buffered-file->buffer)
 6055     (clear-stream _test-error-stream)
 6056     (clear-stream $_test-error-buffered-file->buffer)
 6057     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6058     68/push 0/imm32
 6059     68/push 0/imm32
 6060     89/<- %edx 4/r32/esp
 6061     (tailor-exit-descriptor %edx 0x10)
 6062     #
 6063     (write _test-input-stream "fn foo {\n")
 6064     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 6065     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 6066     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 6067     (write _test-input-stream "  c, b <- add a\n")
 6068     (write _test-input-stream "}\n")
 6069     # convert
 6070     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6071     # registers except esp clobbered at this point
 6072     # restore ed
 6073     89/<- %edx 4/r32/esp
 6074     (flush _test-output-buffered-file)
 6075     (flush _test-error-buffered-file)
 6076 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6082     # check output
 6083     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 6084     (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")
 6085     # check that stop(1) was called
 6086     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 6087     # don't restore from ebp
 6088     81 0/subop/add %esp 8/imm32
 6089     # . epilogue
 6090     5d/pop-to-ebp
 6091     c3/return
 6092 
 6093 test-add-with-non-number:
 6094     # . prologue
 6095     55/push-ebp
 6096     89/<- %ebp 4/r32/esp
 6097     # setup
 6098     (clear-stream _test-input-stream)
 6099     (clear-stream $_test-input-buffered-file->buffer)
 6100     (clear-stream _test-output-stream)
 6101     (clear-stream $_test-output-buffered-file->buffer)
 6102     (clear-stream _test-error-stream)
 6103     (clear-stream $_test-error-buffered-file->buffer)
 6104     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6105     68/push 0/imm32
 6106     68/push 0/imm32
 6107     89/<- %edx 4/r32/esp
 6108     (tailor-exit-descriptor %edx 0x10)
 6109     #
 6110     (write _test-input-stream "fn foo {\n")
 6111     (write _test-input-stream "  var a: int\n")
 6112     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 6113     (write _test-input-stream "}\n")
 6114     # convert
 6115     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6116     # registers except esp clobbered at this point
 6117     # restore ed
 6118     89/<- %edx 4/r32/esp
 6119     (flush _test-output-buffered-file)
 6120     (flush _test-error-buffered-file)
 6121 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6127     # check output
 6128     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 6129     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: only non-addr scalar args permitted"  "F - test-add-with-non-number: error message")
 6130     # check that stop(1) was called
 6131     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 6132     # don't restore from ebp
 6133     81 0/subop/add %esp 8/imm32
 6134     # . epilogue
 6135     5d/pop-to-ebp
 6136     c3/return
 6137 
 6138 test-add-with-addr-dereferenced:
 6139     # . prologue
 6140     55/push-ebp
 6141     89/<- %ebp 4/r32/esp
 6142     # setup
 6143     (clear-stream _test-input-stream)
 6144     (clear-stream $_test-input-buffered-file->buffer)
 6145     (clear-stream _test-output-stream)
 6146     (clear-stream $_test-output-buffered-file->buffer)
 6147     #
 6148     (write _test-input-stream "fn foo {\n")
 6149     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 6150     (write _test-input-stream "  add-to *a, 1\n")
 6151     (write _test-input-stream "}\n")
 6152     # convert
 6153     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6154     (flush _test-output-buffered-file)
 6155     # no error
 6156     # . epilogue
 6157     89/<- %esp 5/r32/ebp
 6158     5d/pop-to-ebp
 6159     c3/return
 6160 
 6161 test-get-with-wrong-field:
 6162     # . prologue
 6163     55/push-ebp
 6164     89/<- %ebp 4/r32/esp
 6165     # setup
 6166     (clear-stream _test-input-stream)
 6167     (clear-stream $_test-input-buffered-file->buffer)
 6168     (clear-stream _test-output-stream)
 6169     (clear-stream $_test-output-buffered-file->buffer)
 6170     (clear-stream _test-error-stream)
 6171     (clear-stream $_test-error-buffered-file->buffer)
 6172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6173     68/push 0/imm32
 6174     68/push 0/imm32
 6175     89/<- %edx 4/r32/esp
 6176     (tailor-exit-descriptor %edx 0x10)
 6177     #
 6178     (write _test-input-stream "fn foo {\n")
 6179     (write _test-input-stream "  var a: t\n")
 6180     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6181     (write _test-input-stream "}\n")
 6182     (write _test-input-stream "type t {\n")
 6183     (write _test-input-stream "  x: int\n")
 6184     (write _test-input-stream "}\n")
 6185     # convert
 6186     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6187     # registers except esp clobbered at this point
 6188     # restore ed
 6189     89/<- %edx 4/r32/esp
 6190     (flush _test-output-buffered-file)
 6191     (flush _test-error-buffered-file)
 6192 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6198     # check output
 6199     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 6200     (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")
 6201     # check that stop(1) was called
 6202     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 6203     # don't restore from ebp
 6204     81 0/subop/add %esp 8/imm32
 6205     # . epilogue
 6206     5d/pop-to-ebp
 6207     c3/return
 6208 
 6209 test-get-with-wrong-base-type:
 6210     # . prologue
 6211     55/push-ebp
 6212     89/<- %ebp 4/r32/esp
 6213     # setup
 6214     (clear-stream _test-input-stream)
 6215     (clear-stream $_test-input-buffered-file->buffer)
 6216     (clear-stream _test-output-stream)
 6217     (clear-stream $_test-output-buffered-file->buffer)
 6218     (clear-stream _test-error-stream)
 6219     (clear-stream $_test-error-buffered-file->buffer)
 6220     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6221     68/push 0/imm32
 6222     68/push 0/imm32
 6223     89/<- %edx 4/r32/esp
 6224     (tailor-exit-descriptor %edx 0x10)
 6225     #
 6226     (write _test-input-stream "fn foo {\n")
 6227     (write _test-input-stream "  var a: int\n")
 6228     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6229     (write _test-input-stream "}\n")
 6230     # convert
 6231     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6232     # registers except esp clobbered at this point
 6233     # restore ed
 6234     89/<- %edx 4/r32/esp
 6235     (flush _test-output-buffered-file)
 6236     (flush _test-error-buffered-file)
 6237 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6243     # check output
 6244     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 6245     (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")
 6246     # check that stop(1) was called
 6247     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 6248     # don't restore from ebp
 6249     81 0/subop/add %esp 8/imm32
 6250     # . epilogue
 6251     5d/pop-to-ebp
 6252     c3/return
 6253 
 6254 test-get-with-wrong-base-type-2:
 6255     # . prologue
 6256     55/push-ebp
 6257     89/<- %ebp 4/r32/esp
 6258     # setup
 6259     (clear-stream _test-input-stream)
 6260     (clear-stream $_test-input-buffered-file->buffer)
 6261     (clear-stream _test-output-stream)
 6262     (clear-stream $_test-output-buffered-file->buffer)
 6263     (clear-stream _test-error-stream)
 6264     (clear-stream $_test-error-buffered-file->buffer)
 6265     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6266     68/push 0/imm32
 6267     68/push 0/imm32
 6268     89/<- %edx 4/r32/esp
 6269     (tailor-exit-descriptor %edx 0x10)
 6270     #
 6271     (write _test-input-stream "fn foo {\n")
 6272     (write _test-input-stream "  var a: (addr t)\n")
 6273     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6274     (write _test-input-stream "}\n")
 6275     (write _test-input-stream "type t {\n")
 6276     (write _test-input-stream "  x: int\n")
 6277     (write _test-input-stream "}\n")
 6278     # convert
 6279     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6280     # registers except esp clobbered at this point
 6281     # restore ed
 6282     89/<- %edx 4/r32/esp
 6283     (flush _test-output-buffered-file)
 6284     (flush _test-error-buffered-file)
 6285 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6291     # check output
 6292     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 6293     (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")
 6294     # check that stop(1) was called
 6295     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 6296     # don't restore from ebp
 6297     81 0/subop/add %esp 8/imm32
 6298     # . epilogue
 6299     5d/pop-to-ebp
 6300     c3/return
 6301 
 6302 test-get-with-wrong-offset-type:
 6303     # . prologue
 6304     55/push-ebp
 6305     89/<- %ebp 4/r32/esp
 6306     # setup
 6307     (clear-stream _test-input-stream)
 6308     (clear-stream $_test-input-buffered-file->buffer)
 6309     (clear-stream _test-output-stream)
 6310     (clear-stream $_test-output-buffered-file->buffer)
 6311     (clear-stream _test-error-stream)
 6312     (clear-stream $_test-error-buffered-file->buffer)
 6313     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6314     68/push 0/imm32
 6315     68/push 0/imm32
 6316     89/<- %edx 4/r32/esp
 6317     (tailor-exit-descriptor %edx 0x10)
 6318     #
 6319     (write _test-input-stream "fn foo {\n")
 6320     (write _test-input-stream "  var a: t\n")
 6321     (write _test-input-stream "  var b: int\n")
 6322     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 6323     (write _test-input-stream "}\n")
 6324     (write _test-input-stream "type t {\n")
 6325     (write _test-input-stream "  x: int\n")
 6326     (write _test-input-stream "}\n")
 6327     # convert
 6328     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6329     # registers except esp clobbered at this point
 6330     # restore ed
 6331     89/<- %edx 4/r32/esp
 6332     (flush _test-output-buffered-file)
 6333     (flush _test-error-buffered-file)
 6334 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6340     # check output
 6341     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 6342     (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")
 6343     # check that stop(1) was called
 6344     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 6345     # don't restore from ebp
 6346     81 0/subop/add %esp 8/imm32
 6347     # . epilogue
 6348     5d/pop-to-ebp
 6349     c3/return
 6350 
 6351 test-get-with-wrong-output-type:
 6352     # . prologue
 6353     55/push-ebp
 6354     89/<- %ebp 4/r32/esp
 6355     # setup
 6356     (clear-stream _test-input-stream)
 6357     (clear-stream $_test-input-buffered-file->buffer)
 6358     (clear-stream _test-output-stream)
 6359     (clear-stream $_test-output-buffered-file->buffer)
 6360     (clear-stream _test-error-stream)
 6361     (clear-stream $_test-error-buffered-file->buffer)
 6362     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6363     68/push 0/imm32
 6364     68/push 0/imm32
 6365     89/<- %edx 4/r32/esp
 6366     (tailor-exit-descriptor %edx 0x10)
 6367     #
 6368     (write _test-input-stream "fn foo {\n")
 6369     (write _test-input-stream "  var a: t\n")
 6370     (write _test-input-stream "  var c: (addr int)\n")
 6371     (write _test-input-stream "  c <- get a, x\n")
 6372     (write _test-input-stream "}\n")
 6373     (write _test-input-stream "type t {\n")
 6374     (write _test-input-stream "  x: int\n")
 6375     (write _test-input-stream "}\n")
 6376     # convert
 6377     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6378     # registers except esp clobbered at this point
 6379     # restore ed
 6380     89/<- %edx 4/r32/esp
 6381     (flush _test-output-buffered-file)
 6382     (flush _test-error-buffered-file)
 6383 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6389     # check output
 6390     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 6391     (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")
 6392     # check that stop(1) was called
 6393     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 6394     # don't restore from ebp
 6395     81 0/subop/add %esp 8/imm32
 6396     # . epilogue
 6397     5d/pop-to-ebp
 6398     c3/return
 6399 
 6400 test-get-with-wrong-output-type-2:
 6401     # . prologue
 6402     55/push-ebp
 6403     89/<- %ebp 4/r32/esp
 6404     # setup
 6405     (clear-stream _test-input-stream)
 6406     (clear-stream $_test-input-buffered-file->buffer)
 6407     (clear-stream _test-output-stream)
 6408     (clear-stream $_test-output-buffered-file->buffer)
 6409     (clear-stream _test-error-stream)
 6410     (clear-stream $_test-error-buffered-file->buffer)
 6411     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6412     68/push 0/imm32
 6413     68/push 0/imm32
 6414     89/<- %edx 4/r32/esp
 6415     (tailor-exit-descriptor %edx 0x10)
 6416     #
 6417     (write _test-input-stream "fn foo {\n")
 6418     (write _test-input-stream "  var a: t\n")
 6419     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 6420     (write _test-input-stream "}\n")
 6421     (write _test-input-stream "type t {\n")
 6422     (write _test-input-stream "  x: int\n")
 6423     (write _test-input-stream "}\n")
 6424     # convert
 6425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6426     # registers except esp clobbered at this point
 6427     # restore ed
 6428     89/<- %edx 4/r32/esp
 6429     (flush _test-output-buffered-file)
 6430     (flush _test-error-buffered-file)
 6431 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6437     # check output
 6438     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 6439     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an address"  "F - test-get-with-wrong-output-type-2: error message")
 6440     # check that stop(1) was called
 6441     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 6442     # don't restore from ebp
 6443     81 0/subop/add %esp 8/imm32
 6444     # . epilogue
 6445     5d/pop-to-ebp
 6446     c3/return
 6447 
 6448 test-get-with-wrong-output-type-3:
 6449     # . prologue
 6450     55/push-ebp
 6451     89/<- %ebp 4/r32/esp
 6452     # setup
 6453     (clear-stream _test-input-stream)
 6454     (clear-stream $_test-input-buffered-file->buffer)
 6455     (clear-stream _test-output-stream)
 6456     (clear-stream $_test-output-buffered-file->buffer)
 6457     (clear-stream _test-error-stream)
 6458     (clear-stream $_test-error-buffered-file->buffer)
 6459     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6460     68/push 0/imm32
 6461     68/push 0/imm32
 6462     89/<- %edx 4/r32/esp
 6463     (tailor-exit-descriptor %edx 0x10)
 6464     #
 6465     (write _test-input-stream "fn foo {\n")
 6466     (write _test-input-stream "  var a: t\n")
 6467     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 6468     (write _test-input-stream "}\n")
 6469     (write _test-input-stream "type t {\n")
 6470     (write _test-input-stream "  x: int\n")
 6471     (write _test-input-stream "}\n")
 6472     # convert
 6473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6474     # registers except esp clobbered at this point
 6475     # restore ed
 6476     89/<- %edx 4/r32/esp
 6477     (flush _test-output-buffered-file)
 6478     (flush _test-error-buffered-file)
 6479 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6485     # check output
 6486     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 6487     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an address"  "F - test-get-with-wrong-output-type-3: error message")
 6488     # check that stop(1) was called
 6489     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 6490     # don't restore from ebp
 6491     81 0/subop/add %esp 8/imm32
 6492     # . epilogue
 6493     5d/pop-to-ebp
 6494     c3/return
 6495 
 6496 test-get-with-wrong-output-type-4:
 6497     # . prologue
 6498     55/push-ebp
 6499     89/<- %ebp 4/r32/esp
 6500     # setup
 6501     (clear-stream _test-input-stream)
 6502     (clear-stream $_test-input-buffered-file->buffer)
 6503     (clear-stream _test-output-stream)
 6504     (clear-stream $_test-output-buffered-file->buffer)
 6505     (clear-stream _test-error-stream)
 6506     (clear-stream $_test-error-buffered-file->buffer)
 6507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6508     68/push 0/imm32
 6509     68/push 0/imm32
 6510     89/<- %edx 4/r32/esp
 6511     (tailor-exit-descriptor %edx 0x10)
 6512     #
 6513     (write _test-input-stream "fn foo {\n")
 6514     (write _test-input-stream "  var a: t\n")
 6515     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 6516     (write _test-input-stream "}\n")
 6517     (write _test-input-stream "type t {\n")
 6518     (write _test-input-stream "  x: int\n")
 6519     (write _test-input-stream "}\n")
 6520     # convert
 6521     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6522     # registers except esp clobbered at this point
 6523     # restore ed
 6524     89/<- %edx 4/r32/esp
 6525     (flush _test-output-buffered-file)
 6526     (flush _test-error-buffered-file)
 6527 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6533     # check output
 6534     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 6535     (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")
 6536     # check that stop(1) was called
 6537     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 6538     # don't restore from ebp
 6539     81 0/subop/add %esp 8/imm32
 6540     # . epilogue
 6541     5d/pop-to-ebp
 6542     c3/return
 6543 
 6544 test-get-with-wrong-output-type-5:
 6545     # . prologue
 6546     55/push-ebp
 6547     89/<- %ebp 4/r32/esp
 6548     # setup
 6549     (clear-stream _test-input-stream)
 6550     (clear-stream $_test-input-buffered-file->buffer)
 6551     (clear-stream _test-output-stream)
 6552     (clear-stream $_test-output-buffered-file->buffer)
 6553     #
 6554     (write _test-input-stream "fn foo {\n")
 6555     (write _test-input-stream "  var a: t\n")
 6556     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 6557     (write _test-input-stream "}\n")
 6558     (write _test-input-stream "type t {\n")
 6559     (write _test-input-stream "  x: (handle int)\n")
 6560     (write _test-input-stream "}\n")
 6561     # convert
 6562     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6563     (flush _test-output-buffered-file)
 6564     # no errors
 6565     # . epilogue
 6566     89/<- %esp 5/r32/ebp
 6567     5d/pop-to-ebp
 6568     c3/return
 6569 
 6570 test-get-with-too-few-inouts:
 6571     # . prologue
 6572     55/push-ebp
 6573     89/<- %ebp 4/r32/esp
 6574     # setup
 6575     (clear-stream _test-input-stream)
 6576     (clear-stream $_test-input-buffered-file->buffer)
 6577     (clear-stream _test-output-stream)
 6578     (clear-stream $_test-output-buffered-file->buffer)
 6579     (clear-stream _test-error-stream)
 6580     (clear-stream $_test-error-buffered-file->buffer)
 6581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6582     68/push 0/imm32
 6583     68/push 0/imm32
 6584     89/<- %edx 4/r32/esp
 6585     (tailor-exit-descriptor %edx 0x10)
 6586     #
 6587     (write _test-input-stream "fn foo {\n")
 6588     (write _test-input-stream "  var a: t\n")
 6589     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 6590     (write _test-input-stream "}\n")
 6591     (write _test-input-stream "type t {\n")
 6592     (write _test-input-stream "  x: int\n")
 6593     (write _test-input-stream "}\n")
 6594     # convert
 6595     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6596     # registers except esp clobbered at this point
 6597     # restore ed
 6598     89/<- %edx 4/r32/esp
 6599     (flush _test-output-buffered-file)
 6600     (flush _test-error-buffered-file)
 6601 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6607     # check output
 6608     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 6609     (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")
 6610     # check that stop(1) was called
 6611     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 6612     # don't restore from ebp
 6613     81 0/subop/add %esp 8/imm32
 6614     # . epilogue
 6615     5d/pop-to-ebp
 6616     c3/return
 6617 
 6618 test-get-with-too-many-inouts:
 6619     # . prologue
 6620     55/push-ebp
 6621     89/<- %ebp 4/r32/esp
 6622     # setup
 6623     (clear-stream _test-input-stream)
 6624     (clear-stream $_test-input-buffered-file->buffer)
 6625     (clear-stream _test-output-stream)
 6626     (clear-stream $_test-output-buffered-file->buffer)
 6627     (clear-stream _test-error-stream)
 6628     (clear-stream $_test-error-buffered-file->buffer)
 6629     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6630     68/push 0/imm32
 6631     68/push 0/imm32
 6632     89/<- %edx 4/r32/esp
 6633     (tailor-exit-descriptor %edx 0x10)
 6634     #
 6635     (write _test-input-stream "fn foo {\n")
 6636     (write _test-input-stream "  var a: t\n")
 6637     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 6638     (write _test-input-stream "}\n")
 6639     (write _test-input-stream "type t {\n")
 6640     (write _test-input-stream "  x: int\n")
 6641     (write _test-input-stream "}\n")
 6642     # convert
 6643     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6644     # registers except esp clobbered at this point
 6645     # restore ed
 6646     89/<- %edx 4/r32/esp
 6647     (flush _test-output-buffered-file)
 6648     (flush _test-error-buffered-file)
 6649 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6655     # check output
 6656     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 6657     (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")
 6658     # check that stop(1) was called
 6659     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 6660     # don't restore from ebp
 6661     81 0/subop/add %esp 8/imm32
 6662     # . epilogue
 6663     5d/pop-to-ebp
 6664     c3/return
 6665 
 6666 test-get-with-no-output:
 6667     # . prologue
 6668     55/push-ebp
 6669     89/<- %ebp 4/r32/esp
 6670     # setup
 6671     (clear-stream _test-input-stream)
 6672     (clear-stream $_test-input-buffered-file->buffer)
 6673     (clear-stream _test-output-stream)
 6674     (clear-stream $_test-output-buffered-file->buffer)
 6675     (clear-stream _test-error-stream)
 6676     (clear-stream $_test-error-buffered-file->buffer)
 6677     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6678     68/push 0/imm32
 6679     68/push 0/imm32
 6680     89/<- %edx 4/r32/esp
 6681     (tailor-exit-descriptor %edx 0x10)
 6682     #
 6683     (write _test-input-stream "fn foo {\n")
 6684     (write _test-input-stream "  var a: t\n")
 6685     (write _test-input-stream "  get a, x\n")
 6686     (write _test-input-stream "}\n")
 6687     (write _test-input-stream "type t {\n")
 6688     (write _test-input-stream "  x: int\n")
 6689     (write _test-input-stream "}\n")
 6690     # convert
 6691     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6692     # registers except esp clobbered at this point
 6693     # restore ed
 6694     89/<- %edx 4/r32/esp
 6695     (flush _test-output-buffered-file)
 6696     (flush _test-error-buffered-file)
 6697 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6703     # check output
 6704     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 6705     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 6706     # check that stop(1) was called
 6707     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 6708     # don't restore from ebp
 6709     81 0/subop/add %esp 8/imm32
 6710     # . epilogue
 6711     5d/pop-to-ebp
 6712     c3/return
 6713 
 6714 test-get-with-too-many-outputs:
 6715     # . prologue
 6716     55/push-ebp
 6717     89/<- %ebp 4/r32/esp
 6718     # setup
 6719     (clear-stream _test-input-stream)
 6720     (clear-stream $_test-input-buffered-file->buffer)
 6721     (clear-stream _test-output-stream)
 6722     (clear-stream $_test-output-buffered-file->buffer)
 6723     (clear-stream _test-error-stream)
 6724     (clear-stream $_test-error-buffered-file->buffer)
 6725     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6726     68/push 0/imm32
 6727     68/push 0/imm32
 6728     89/<- %edx 4/r32/esp
 6729     (tailor-exit-descriptor %edx 0x10)
 6730     #
 6731     (write _test-input-stream "fn foo {\n")
 6732     (write _test-input-stream "  var a: t\n")
 6733     (write _test-input-stream "  var b: int\n")
 6734     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 6735     (write _test-input-stream "  c, b <- get a, x\n")
 6736     (write _test-input-stream "}\n")
 6737     (write _test-input-stream "type t {\n")
 6738     (write _test-input-stream "  x: int\n")
 6739     (write _test-input-stream "}\n")
 6740     # convert
 6741     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6742     # registers except esp clobbered at this point
 6743     # restore ed
 6744     89/<- %edx 4/r32/esp
 6745     (flush _test-output-buffered-file)
 6746     (flush _test-error-buffered-file)
 6747 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 6753     # check output
 6754     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 6755     (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")
 6756     # check that stop(1) was called
 6757     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 6758     # don't restore from ebp
 6759     81 0/subop/add %esp 8/imm32
 6760     # . epilogue
 6761     5d/pop-to-ebp
 6762     c3/return
 6763 
 6764 test-convert-array-of-user-defined-types:
 6765     # . prologue
 6766     55/push-ebp
 6767     89/<- %ebp 4/r32/esp
 6768     # setup
 6769     (clear-stream _test-input-stream)
 6770     (clear-stream $_test-input-buffered-file->buffer)
 6771     (clear-stream _test-output-stream)
 6772     (clear-stream $_test-output-buffered-file->buffer)
 6773     #
 6774     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 6775     (write _test-input-stream "  x: int\n")
 6776     (write _test-input-stream "  y: int\n")
 6777     (write _test-input-stream "}\n")
 6778     (write _test-input-stream "fn foo {\n")
 6779     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6780     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6781     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 6782     (write _test-input-stream "}\n")
 6783     # convert
 6784     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6785     (flush _test-output-buffered-file)
 6786 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6792     # check output
 6793     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 6794     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 6795     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 6796     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 6797     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 6798     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 6799     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 6800     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 6801     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 6802     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 6803     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/11")
 6804     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/13")
 6805     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/14")
 6806     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/15")
 6807     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/16")
 6808     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/17")
 6809     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/18")
 6810     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/19")
 6811     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/20")
 6812     # . epilogue
 6813     89/<- %esp 5/r32/ebp
 6814     5d/pop-to-ebp
 6815     c3/return
 6816 
 6817 test-convert-length-of-array-of-user-defined-types-to-eax:
 6818     # . prologue
 6819     55/push-ebp
 6820     89/<- %ebp 4/r32/esp
 6821     # setup
 6822     (clear-stream _test-input-stream)
 6823     (clear-stream $_test-input-buffered-file->buffer)
 6824     (clear-stream _test-output-stream)
 6825     (clear-stream $_test-output-buffered-file->buffer)
 6826     #
 6827     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 6828     (write _test-input-stream "  x: int\n")
 6829     (write _test-input-stream "  y: int\n")
 6830     (write _test-input-stream "  z: int\n")
 6831     (write _test-input-stream "}\n")
 6832     (write _test-input-stream "fn foo {\n")
 6833     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6834     (write _test-input-stream "  var x/eax: (addr t) <- length arr\n")
 6835     (write _test-input-stream "}\n")
 6836     # convert
 6837     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6838     (flush _test-output-buffered-file)
 6839 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6845     # check output
 6846     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 6847     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 6848     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 6849     (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")
 6850     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 6851     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 6852     # var arr
 6853     (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")
 6854     (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")
 6855     # length instruction
 6856     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 6857     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 6858     (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")
 6859     (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")
 6860     (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")
 6861     (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")
 6862     (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")
 6863     (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")
 6864     # reclaim arr
 6865     (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")
 6866     #
 6867     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 6868     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 6869     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 6870     (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")
 6871     (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")
 6872     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 6873     # . epilogue
 6874     89/<- %esp 5/r32/ebp
 6875     5d/pop-to-ebp
 6876     c3/return
 6877 
 6878 test-convert-length-of-array-of-user-defined-types-to-ecx:
 6879     # . prologue
 6880     55/push-ebp
 6881     89/<- %ebp 4/r32/esp
 6882     # setup
 6883     (clear-stream _test-input-stream)
 6884     (clear-stream $_test-input-buffered-file->buffer)
 6885     (clear-stream _test-output-stream)
 6886     (clear-stream $_test-output-buffered-file->buffer)
 6887     #
 6888     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 6889     (write _test-input-stream "  x: int\n")
 6890     (write _test-input-stream "  y: int\n")
 6891     (write _test-input-stream "  z: int\n")
 6892     (write _test-input-stream "}\n")
 6893     (write _test-input-stream "fn foo {\n")
 6894     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6895     (write _test-input-stream "  var x/ecx: (addr t) <- length arr\n")
 6896     (write _test-input-stream "}\n")
 6897     # convert
 6898     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6899     (flush _test-output-buffered-file)
 6900 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6906     # check output
 6907     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 6908     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 6909     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 6910     (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")
 6911     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 6912     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 6913     # var a
 6914     (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")
 6915     (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")
 6916     # var x
 6917     (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")
 6918     # length instruction
 6919     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 6920     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 6921     (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")
 6922     (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")
 6923     (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")
 6924     (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")
 6925     (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")
 6926     (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")
 6927     (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")
 6928     # reclaim x
 6929     (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")
 6930     # reclaim a
 6931     (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")
 6932     #
 6933     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 6934     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 6935     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 6936     (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")
 6937     (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")
 6938     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 6939     # . epilogue
 6940     89/<- %esp 5/r32/ebp
 6941     5d/pop-to-ebp
 6942     c3/return
 6943 
 6944 test-convert-length-of-array-of-user-defined-types-to-edx:
 6945     # . prologue
 6946     55/push-ebp
 6947     89/<- %ebp 4/r32/esp
 6948     # setup
 6949     (clear-stream _test-input-stream)
 6950     (clear-stream $_test-input-buffered-file->buffer)
 6951     (clear-stream _test-output-stream)
 6952     (clear-stream $_test-output-buffered-file->buffer)
 6953     #
 6954     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 6955     (write _test-input-stream "  x: int\n")
 6956     (write _test-input-stream "  y: int\n")
 6957     (write _test-input-stream "  z: int\n")
 6958     (write _test-input-stream "}\n")
 6959     (write _test-input-stream "fn foo {\n")
 6960     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 6961     (write _test-input-stream "  var x/edx: (addr t) <- length arr\n")
 6962     (write _test-input-stream "}\n")
 6963     # convert
 6964     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6965     (flush _test-output-buffered-file)
 6966 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 6972     # check output
 6973     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 6974     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 6975     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 6976     (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")
 6977     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 6978     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 6979     # var a
 6980     (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")
 6981     (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")
 6982     # var x
 6983     (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")
 6984     # length instruction
 6985     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 6986     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 6987     (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")
 6988     (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")
 6989     (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")
 6990     (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")
 6991     (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")
 6992     (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")
 6993     (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")
 6994     # reclaim x
 6995     (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")
 6996     # reclaim a
 6997     (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")
 6998     #
 6999     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 7000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 7001     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 7002     (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")
 7003     (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")
 7004     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 7005     # . epilogue
 7006     89/<- %esp 5/r32/ebp
 7007     5d/pop-to-ebp
 7008     c3/return
 7009 
 7010 test-convert-length-of-array-of-user-defined-types:
 7011     # . prologue
 7012     55/push-ebp
 7013     89/<- %ebp 4/r32/esp
 7014     # setup
 7015     (clear-stream _test-input-stream)
 7016     (clear-stream $_test-input-buffered-file->buffer)
 7017     (clear-stream _test-output-stream)
 7018     (clear-stream $_test-output-buffered-file->buffer)
 7019     #
 7020     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 7021     (write _test-input-stream "  x: int\n")
 7022     (write _test-input-stream "  y: int\n")
 7023     (write _test-input-stream "  z: int\n")
 7024     (write _test-input-stream "}\n")
 7025     (write _test-input-stream "fn foo {\n")
 7026     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 7027     (write _test-input-stream "  var x/ebx: (addr t) <- length arr\n")
 7028     (write _test-input-stream "}\n")
 7029     # convert
 7030     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7031     (flush _test-output-buffered-file)
 7032 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
 7038     # check output
 7039     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 7040     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 7041     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 7042     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 7043     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 7044     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 7045     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 7046     (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")
 7047     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 7048     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 7049     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 7050     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 7051     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 7052     (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")
 7053     (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")
 7054     (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")
 7055     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 7056     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 7057     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 7058     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 7059     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 7060     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 7061     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 7062     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 7063     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 7064     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 7065     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 7066     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 7067     # . epilogue
 7068     89/<- %esp 5/r32/ebp
 7069     5d/pop-to-ebp
 7070     c3/return
 7071 
 7072 test-index-with-non-array-atom-base-type:
 7073     # . prologue
 7074     55/push-ebp
 7075     89/<- %ebp 4/r32/esp
 7076     # setup
 7077     (clear-stream _test-input-stream)
 7078     (clear-stream $_test-input-buffered-file->buffer)
 7079     (clear-stream _test-output-stream)
 7080     (clear-stream $_test-output-buffered-file->buffer)
 7081     (clear-stream _test-error-stream)
 7082     (clear-stream $_test-error-buffered-file->buffer)
 7083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7084     68/push 0/imm32
 7085     68/push 0/imm32
 7086     89/<- %edx 4/r32/esp
 7087     (tailor-exit-descriptor %edx 0x10)
 7088     #
 7089     (write _test-input-stream "fn foo {\n")
 7090     (write _test-input-stream "  var a: int\n")
 7091     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7092     (write _test-input-stream "}\n")
 7093     # convert
 7094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7095     # registers except esp clobbered at this point
 7096     # restore ed
 7097     89/<- %edx 4/r32/esp
 7098     (flush _test-output-buffered-file)
 7099     (flush _test-error-buffered-file)
 7100 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7106     # check output
 7107     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 7108     (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")
 7109     # check that stop(1) was called
 7110     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 7111     # don't restore from ebp
 7112     81 0/subop/add %esp 8/imm32
 7113     # . epilogue
 7114     5d/pop-to-ebp
 7115     c3/return
 7116 
 7117 test-index-with-non-array-compound-base-type:
 7118     # . prologue
 7119     55/push-ebp
 7120     89/<- %ebp 4/r32/esp
 7121     # setup
 7122     (clear-stream _test-input-stream)
 7123     (clear-stream $_test-input-buffered-file->buffer)
 7124     (clear-stream _test-output-stream)
 7125     (clear-stream $_test-output-buffered-file->buffer)
 7126     (clear-stream _test-error-stream)
 7127     (clear-stream $_test-error-buffered-file->buffer)
 7128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7129     68/push 0/imm32
 7130     68/push 0/imm32
 7131     89/<- %edx 4/r32/esp
 7132     (tailor-exit-descriptor %edx 0x10)
 7133     #
 7134     (write _test-input-stream "fn foo {\n")
 7135     (write _test-input-stream "  var a: (handle int)\n")
 7136     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7137     (write _test-input-stream "}\n")
 7138     # convert
 7139     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7140     # registers except esp clobbered at this point
 7141     # restore ed
 7142     89/<- %edx 4/r32/esp
 7143     (flush _test-output-buffered-file)
 7144     (flush _test-error-buffered-file)
 7145 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7151     # check output
 7152     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 7153     (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")
 7154     # check that stop(1) was called
 7155     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 7156     # don't restore from ebp
 7157     81 0/subop/add %esp 8/imm32
 7158     # . epilogue
 7159     5d/pop-to-ebp
 7160     c3/return
 7161 
 7162 test-index-with-non-array-compound-base-type-2:
 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     (clear-stream _test-error-stream)
 7172     (clear-stream $_test-error-buffered-file->buffer)
 7173     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7174     68/push 0/imm32
 7175     68/push 0/imm32
 7176     89/<- %edx 4/r32/esp
 7177     (tailor-exit-descriptor %edx 0x10)
 7178     #
 7179     (write _test-input-stream "fn foo {\n")
 7180     (write _test-input-stream "  var a: (addr int)\n")
 7181     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7182     (write _test-input-stream "}\n")
 7183     # convert
 7184     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7185     # registers except esp clobbered at this point
 7186     # restore ed
 7187     89/<- %edx 4/r32/esp
 7188     (flush _test-output-buffered-file)
 7189     (flush _test-error-buffered-file)
 7190 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7196     # check output
 7197     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 7198     (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")
 7199     # check that stop(1) was called
 7200     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 7201     # don't restore from ebp
 7202     81 0/subop/add %esp 8/imm32
 7203     # . epilogue
 7204     5d/pop-to-ebp
 7205     c3/return
 7206 
 7207 test-index-with-array-atom-base-type:
 7208     # . prologue
 7209     55/push-ebp
 7210     89/<- %ebp 4/r32/esp
 7211     # setup
 7212     (clear-stream _test-input-stream)
 7213     (clear-stream $_test-input-buffered-file->buffer)
 7214     (clear-stream _test-output-stream)
 7215     (clear-stream $_test-output-buffered-file->buffer)
 7216     (clear-stream _test-error-stream)
 7217     (clear-stream $_test-error-buffered-file->buffer)
 7218     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7219     68/push 0/imm32
 7220     68/push 0/imm32
 7221     89/<- %edx 4/r32/esp
 7222     (tailor-exit-descriptor %edx 0x10)
 7223     #
 7224     (write _test-input-stream "fn foo {\n")
 7225     (write _test-input-stream "  var a: array\n")
 7226     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7227     (write _test-input-stream "}\n")
 7228     # convert
 7229     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7230     # registers except esp clobbered at this point
 7231     # restore ed
 7232     89/<- %edx 4/r32/esp
 7233     (flush _test-output-buffered-file)
 7234     (flush _test-error-buffered-file)
 7235 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7241     # check output
 7242     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 7243     (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")
 7244     # check that stop(1) was called
 7245     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 7246     # don't restore from ebp
 7247     81 0/subop/add %esp 8/imm32
 7248     # . epilogue
 7249     5d/pop-to-ebp
 7250     c3/return
 7251 
 7252 test-index-with-addr-base-on-stack:
 7253     # . prologue
 7254     55/push-ebp
 7255     89/<- %ebp 4/r32/esp
 7256     # setup
 7257     (clear-stream _test-input-stream)
 7258     (clear-stream $_test-input-buffered-file->buffer)
 7259     (clear-stream _test-output-stream)
 7260     (clear-stream $_test-output-buffered-file->buffer)
 7261     (clear-stream _test-error-stream)
 7262     (clear-stream $_test-error-buffered-file->buffer)
 7263     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7264     68/push 0/imm32
 7265     68/push 0/imm32
 7266     89/<- %edx 4/r32/esp
 7267     (tailor-exit-descriptor %edx 0x10)
 7268     #
 7269     (write _test-input-stream "fn foo {\n")
 7270     (write _test-input-stream "  var a: (addr array int)\n")
 7271     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7272     (write _test-input-stream "}\n")
 7273     # convert
 7274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7275     # registers except esp clobbered at this point
 7276     # restore ed
 7277     89/<- %edx 4/r32/esp
 7278     (flush _test-output-buffered-file)
 7279     (flush _test-error-buffered-file)
 7280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7286     # check output
 7287     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
 7288     (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")
 7289     # check that stop(1) was called
 7290     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
 7291     # don't restore from ebp
 7292     81 0/subop/add %esp 8/imm32
 7293     # . epilogue
 7294     5d/pop-to-ebp
 7295     c3/return
 7296 
 7297 test-index-with-array-base-in-register:
 7298     # . prologue
 7299     55/push-ebp
 7300     89/<- %ebp 4/r32/esp
 7301     # setup
 7302     (clear-stream _test-input-stream)
 7303     (clear-stream $_test-input-buffered-file->buffer)
 7304     (clear-stream _test-output-stream)
 7305     (clear-stream $_test-output-buffered-file->buffer)
 7306     (clear-stream _test-error-stream)
 7307     (clear-stream $_test-error-buffered-file->buffer)
 7308     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7309     68/push 0/imm32
 7310     68/push 0/imm32
 7311     89/<- %edx 4/r32/esp
 7312     (tailor-exit-descriptor %edx 0x10)
 7313     #
 7314     (write _test-input-stream "fn foo {\n")
 7315     (write _test-input-stream "  var a/eax: (array int 3) <- copy 0\n")
 7316     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 7317     (write _test-input-stream "}\n")
 7318     # convert
 7319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7320     # registers except esp clobbered at this point
 7321     # restore ed
 7322     89/<- %edx 4/r32/esp
 7323     (flush _test-output-buffered-file)
 7324     (flush _test-error-buffered-file)
 7325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7331     # check output
 7332     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-base-in-register: output should be empty")
 7333     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is an array, and so must live on the stack"  "F - test-index-with-array-base-in-register: error message")
 7334     # check that stop(1) was called
 7335     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-base-in-register: exit status")
 7336     # don't restore from ebp
 7337     81 0/subop/add %esp 8/imm32
 7338     # . epilogue
 7339     5d/pop-to-ebp
 7340     c3/return
 7341 
 7342 test-index-with-wrong-index-type:
 7343     # . prologue
 7344     55/push-ebp
 7345     89/<- %ebp 4/r32/esp
 7346     # setup
 7347     (clear-stream _test-input-stream)
 7348     (clear-stream $_test-input-buffered-file->buffer)
 7349     (clear-stream _test-output-stream)
 7350     (clear-stream $_test-output-buffered-file->buffer)
 7351     (clear-stream _test-error-stream)
 7352     (clear-stream $_test-error-buffered-file->buffer)
 7353     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7354     68/push 0/imm32
 7355     68/push 0/imm32
 7356     89/<- %edx 4/r32/esp
 7357     (tailor-exit-descriptor %edx 0x10)
 7358     #
 7359     (write _test-input-stream "fn foo {\n")
 7360     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7361     (write _test-input-stream "  var b: boolean\n")
 7362     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7363     (write _test-input-stream "}\n")
 7364     # convert
 7365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7366     # registers except esp clobbered at this point
 7367     # restore ed
 7368     89/<- %edx 4/r32/esp
 7369     (flush _test-output-buffered-file)
 7370     (flush _test-error-buffered-file)
 7371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7377     # check output
 7378     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
 7379     (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")
 7380     # check that stop(1) was called
 7381     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
 7382     # don't restore from ebp
 7383     81 0/subop/add %esp 8/imm32
 7384     # . epilogue
 7385     5d/pop-to-ebp
 7386     c3/return
 7387 
 7388 test-index-with-offset-atom-index-type:
 7389     # . prologue
 7390     55/push-ebp
 7391     89/<- %ebp 4/r32/esp
 7392     # setup
 7393     (clear-stream _test-input-stream)
 7394     (clear-stream $_test-input-buffered-file->buffer)
 7395     (clear-stream _test-output-stream)
 7396     (clear-stream $_test-output-buffered-file->buffer)
 7397     (clear-stream _test-error-stream)
 7398     (clear-stream $_test-error-buffered-file->buffer)
 7399     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7400     68/push 0/imm32
 7401     68/push 0/imm32
 7402     89/<- %edx 4/r32/esp
 7403     (tailor-exit-descriptor %edx 0x10)
 7404     #
 7405     (write _test-input-stream "fn foo {\n")
 7406     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7407     (write _test-input-stream "  var b: offset\n")
 7408     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7409     (write _test-input-stream "}\n")
 7410     # convert
 7411     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7412     # registers except esp clobbered at this point
 7413     # restore ed
 7414     89/<- %edx 4/r32/esp
 7415     (flush _test-output-buffered-file)
 7416     (flush _test-error-buffered-file)
 7417 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7423     # check output
 7424     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
 7425     (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")
 7426     # check that stop(1) was called
 7427     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
 7428     # don't restore from ebp
 7429     81 0/subop/add %esp 8/imm32
 7430     # . epilogue
 7431     5d/pop-to-ebp
 7432     c3/return
 7433 
 7434 test-index-with-offset-on-stack:
 7435     # . prologue
 7436     55/push-ebp
 7437     89/<- %ebp 4/r32/esp
 7438     # setup
 7439     (clear-stream _test-input-stream)
 7440     (clear-stream $_test-input-buffered-file->buffer)
 7441     (clear-stream _test-output-stream)
 7442     (clear-stream $_test-output-buffered-file->buffer)
 7443     (clear-stream _test-error-stream)
 7444     (clear-stream $_test-error-buffered-file->buffer)
 7445     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7446     68/push 0/imm32
 7447     68/push 0/imm32
 7448     89/<- %edx 4/r32/esp
 7449     (tailor-exit-descriptor %edx 0x10)
 7450     #
 7451     (write _test-input-stream "fn foo {\n")
 7452     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
 7453     (write _test-input-stream "  var b: int\n")
 7454     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7455     (write _test-input-stream "}\n")
 7456     # convert
 7457     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7458     # registers except esp clobbered at this point
 7459     # restore ed
 7460     89/<- %edx 4/r32/esp
 7461     (flush _test-output-buffered-file)
 7462     (flush _test-error-buffered-file)
 7463 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7469     # check output
 7470     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
 7471     (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")
 7472     # check that stop(1) was called
 7473     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
 7474     # don't restore from ebp
 7475     81 0/subop/add %esp 8/imm32
 7476     # . epilogue
 7477     5d/pop-to-ebp
 7478     c3/return
 7479 
 7480 test-index-needs-offset-type:
 7481     # . prologue
 7482     55/push-ebp
 7483     89/<- %ebp 4/r32/esp
 7484     # setup
 7485     (clear-stream _test-input-stream)
 7486     (clear-stream $_test-input-buffered-file->buffer)
 7487     (clear-stream _test-output-stream)
 7488     (clear-stream $_test-output-buffered-file->buffer)
 7489     (clear-stream _test-error-stream)
 7490     (clear-stream $_test-error-buffered-file->buffer)
 7491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7492     68/push 0/imm32
 7493     68/push 0/imm32
 7494     89/<- %edx 4/r32/esp
 7495     (tailor-exit-descriptor %edx 0x10)
 7496     #
 7497     (write _test-input-stream "fn foo {\n")
 7498     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
 7499     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7500     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
 7501     (write _test-input-stream "}\n")
 7502     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
 7503     (write _test-input-stream "  x: int\n")
 7504     (write _test-input-stream "  y: int\n")
 7505     (write _test-input-stream "  z: int\n")
 7506     (write _test-input-stream "}\n")
 7507     # convert
 7508     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7509     # registers except esp clobbered at this point
 7510     # restore ed
 7511     89/<- %edx 4/r32/esp
 7512     (flush _test-output-buffered-file)
 7513     (flush _test-error-buffered-file)
 7514 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7520     # check output
 7521     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
 7522     (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")
 7523     # check that stop(1) was called
 7524     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
 7525     # don't restore from ebp
 7526     81 0/subop/add %esp 8/imm32
 7527     # . epilogue
 7528     5d/pop-to-ebp
 7529     c3/return
 7530 
 7531 test-index-with-output-not-address:
 7532     # . prologue
 7533     55/push-ebp
 7534     89/<- %ebp 4/r32/esp
 7535     # setup
 7536     (clear-stream _test-input-stream)
 7537     (clear-stream $_test-input-buffered-file->buffer)
 7538     (clear-stream _test-output-stream)
 7539     (clear-stream $_test-output-buffered-file->buffer)
 7540     (clear-stream _test-error-stream)
 7541     (clear-stream $_test-error-buffered-file->buffer)
 7542     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7543     68/push 0/imm32
 7544     68/push 0/imm32
 7545     89/<- %edx 4/r32/esp
 7546     (tailor-exit-descriptor %edx 0x10)
 7547     #
 7548     (write _test-input-stream "fn foo {\n")
 7549     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7550     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
 7551     (write _test-input-stream "}\n")
 7552     # convert
 7553     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7554     # registers except esp clobbered at this point
 7555     # restore ed
 7556     89/<- %edx 4/r32/esp
 7557     (flush _test-output-buffered-file)
 7558     (flush _test-error-buffered-file)
 7559 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7565     # check output
 7566     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
 7567     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an address"  "F - test-index-with-output-not-address: error message")
 7568     # check that stop(1) was called
 7569     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
 7570     # don't restore from ebp
 7571     81 0/subop/add %esp 8/imm32
 7572     # . epilogue
 7573     5d/pop-to-ebp
 7574     c3/return
 7575 
 7576 test-index-with-output-not-address-2:
 7577     # . prologue
 7578     55/push-ebp
 7579     89/<- %ebp 4/r32/esp
 7580     # setup
 7581     (clear-stream _test-input-stream)
 7582     (clear-stream $_test-input-buffered-file->buffer)
 7583     (clear-stream _test-output-stream)
 7584     (clear-stream $_test-output-buffered-file->buffer)
 7585     (clear-stream _test-error-stream)
 7586     (clear-stream $_test-error-buffered-file->buffer)
 7587     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7588     68/push 0/imm32
 7589     68/push 0/imm32
 7590     89/<- %edx 4/r32/esp
 7591     (tailor-exit-descriptor %edx 0x10)
 7592     #
 7593     (write _test-input-stream "fn foo {\n")
 7594     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7595     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
 7596     (write _test-input-stream "}\n")
 7597     # convert
 7598     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7599     # registers except esp clobbered at this point
 7600     # restore ed
 7601     89/<- %edx 4/r32/esp
 7602     (flush _test-output-buffered-file)
 7603     (flush _test-error-buffered-file)
 7604 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7610     # check output
 7611     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
 7612     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an address"  "F - test-index-with-output-not-address-2: error message")
 7613     # check that stop(1) was called
 7614     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
 7615     # don't restore from ebp
 7616     81 0/subop/add %esp 8/imm32
 7617     # . epilogue
 7618     5d/pop-to-ebp
 7619     c3/return
 7620 
 7621 test-index-with-wrong-output-type:
 7622     # . prologue
 7623     55/push-ebp
 7624     89/<- %ebp 4/r32/esp
 7625     # setup
 7626     (clear-stream _test-input-stream)
 7627     (clear-stream $_test-input-buffered-file->buffer)
 7628     (clear-stream _test-output-stream)
 7629     (clear-stream $_test-output-buffered-file->buffer)
 7630     (clear-stream _test-error-stream)
 7631     (clear-stream $_test-error-buffered-file->buffer)
 7632     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7633     68/push 0/imm32
 7634     68/push 0/imm32
 7635     89/<- %edx 4/r32/esp
 7636     (tailor-exit-descriptor %edx 0x10)
 7637     #
 7638     (write _test-input-stream "fn foo {\n")
 7639     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
 7640     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
 7641     (write _test-input-stream "}\n")
 7642     # convert
 7643     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7644     # registers except esp clobbered at this point
 7645     # restore ed
 7646     89/<- %edx 4/r32/esp
 7647     (flush _test-output-buffered-file)
 7648     (flush _test-error-buffered-file)
 7649 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7655     # check output
 7656     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
 7657     (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")
 7658     # check that stop(1) was called
 7659     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
 7660     # don't restore from ebp
 7661     81 0/subop/add %esp 8/imm32
 7662     # . epilogue
 7663     5d/pop-to-ebp
 7664     c3/return
 7665 
 7666 test-index-with-wrong-output-compound-type:
 7667     # . prologue
 7668     55/push-ebp
 7669     89/<- %ebp 4/r32/esp
 7670     # setup
 7671     (clear-stream _test-input-stream)
 7672     (clear-stream $_test-input-buffered-file->buffer)
 7673     (clear-stream _test-output-stream)
 7674     (clear-stream $_test-output-buffered-file->buffer)
 7675     (clear-stream _test-error-stream)
 7676     (clear-stream $_test-error-buffered-file->buffer)
 7677     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7678     68/push 0/imm32
 7679     68/push 0/imm32
 7680     89/<- %edx 4/r32/esp
 7681     (tailor-exit-descriptor %edx 0x10)
 7682     #
 7683     (write _test-input-stream "fn foo {\n")
 7684     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
 7685     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
 7686     (write _test-input-stream "}\n")
 7687     # convert
 7688     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7689     # registers except esp clobbered at this point
 7690     # restore ed
 7691     89/<- %edx 4/r32/esp
 7692     (flush _test-output-buffered-file)
 7693     (flush _test-error-buffered-file)
 7694 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7700     # check output
 7701     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
 7702     (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")
 7703     # check that stop(1) was called
 7704     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
 7705     # don't restore from ebp
 7706     81 0/subop/add %esp 8/imm32
 7707     # . epilogue
 7708     5d/pop-to-ebp
 7709     c3/return
 7710 
 7711 test-index-with-no-inouts:
 7712     # . prologue
 7713     55/push-ebp
 7714     89/<- %ebp 4/r32/esp
 7715     # setup
 7716     (clear-stream _test-input-stream)
 7717     (clear-stream $_test-input-buffered-file->buffer)
 7718     (clear-stream _test-output-stream)
 7719     (clear-stream $_test-output-buffered-file->buffer)
 7720     (clear-stream _test-error-stream)
 7721     (clear-stream $_test-error-buffered-file->buffer)
 7722     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7723     68/push 0/imm32
 7724     68/push 0/imm32
 7725     89/<- %edx 4/r32/esp
 7726     (tailor-exit-descriptor %edx 0x10)
 7727     #
 7728     (write _test-input-stream "fn foo {\n")
 7729     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
 7730     (write _test-input-stream "}\n")
 7731     # convert
 7732     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7733     # registers except esp clobbered at this point
 7734     # restore ed
 7735     89/<- %edx 4/r32/esp
 7736     (flush _test-output-buffered-file)
 7737     (flush _test-error-buffered-file)
 7738 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7744     # check output
 7745     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
 7746     (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")
 7747     # check that stop(1) was called
 7748     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
 7749     # don't restore from ebp
 7750     81 0/subop/add %esp 8/imm32
 7751     # . epilogue
 7752     5d/pop-to-ebp
 7753     c3/return
 7754 
 7755 test-index-with-too-few-inouts:
 7756     # . prologue
 7757     55/push-ebp
 7758     89/<- %ebp 4/r32/esp
 7759     # setup
 7760     (clear-stream _test-input-stream)
 7761     (clear-stream $_test-input-buffered-file->buffer)
 7762     (clear-stream _test-output-stream)
 7763     (clear-stream $_test-output-buffered-file->buffer)
 7764     (clear-stream _test-error-stream)
 7765     (clear-stream $_test-error-buffered-file->buffer)
 7766     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7767     68/push 0/imm32
 7768     68/push 0/imm32
 7769     89/<- %edx 4/r32/esp
 7770     (tailor-exit-descriptor %edx 0x10)
 7771     #
 7772     (write _test-input-stream "fn foo {\n")
 7773     (write _test-input-stream "  var a: (array int 3)\n")
 7774     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
 7775     (write _test-input-stream "}\n")
 7776     # convert
 7777     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7778     # registers except esp clobbered at this point
 7779     # restore ed
 7780     89/<- %edx 4/r32/esp
 7781     (flush _test-output-buffered-file)
 7782     (flush _test-error-buffered-file)
 7783 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7789     # check output
 7790     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
 7791     (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")
 7792     # check that stop(1) was called
 7793     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
 7794     # don't restore from ebp
 7795     81 0/subop/add %esp 8/imm32
 7796     # . epilogue
 7797     5d/pop-to-ebp
 7798     c3/return
 7799 
 7800 test-index-with-too-many-inouts:
 7801     # . prologue
 7802     55/push-ebp
 7803     89/<- %ebp 4/r32/esp
 7804     # setup
 7805     (clear-stream _test-input-stream)
 7806     (clear-stream $_test-input-buffered-file->buffer)
 7807     (clear-stream _test-output-stream)
 7808     (clear-stream $_test-output-buffered-file->buffer)
 7809     (clear-stream _test-error-stream)
 7810     (clear-stream $_test-error-buffered-file->buffer)
 7811     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7812     68/push 0/imm32
 7813     68/push 0/imm32
 7814     89/<- %edx 4/r32/esp
 7815     (tailor-exit-descriptor %edx 0x10)
 7816     #
 7817     (write _test-input-stream "fn foo {\n")
 7818     (write _test-input-stream "  var a: (array int 3)\n")
 7819     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
 7820     (write _test-input-stream "}\n")
 7821     # convert
 7822     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7823     # registers except esp clobbered at this point
 7824     # restore ed
 7825     89/<- %edx 4/r32/esp
 7826     (flush _test-output-buffered-file)
 7827     (flush _test-error-buffered-file)
 7828 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7834     # check output
 7835     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
 7836     (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")
 7837     # check that stop(1) was called
 7838     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
 7839     # don't restore from ebp
 7840     81 0/subop/add %esp 8/imm32
 7841     # . epilogue
 7842     5d/pop-to-ebp
 7843     c3/return
 7844 
 7845 test-index-with-no-output:
 7846     # . prologue
 7847     55/push-ebp
 7848     89/<- %ebp 4/r32/esp
 7849     # setup
 7850     (clear-stream _test-input-stream)
 7851     (clear-stream $_test-input-buffered-file->buffer)
 7852     (clear-stream _test-output-stream)
 7853     (clear-stream $_test-output-buffered-file->buffer)
 7854     (clear-stream _test-error-stream)
 7855     (clear-stream $_test-error-buffered-file->buffer)
 7856     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7857     68/push 0/imm32
 7858     68/push 0/imm32
 7859     89/<- %edx 4/r32/esp
 7860     (tailor-exit-descriptor %edx 0x10)
 7861     #
 7862     (write _test-input-stream "fn foo {\n")
 7863     (write _test-input-stream "  var a: (array int 3)\n")
 7864     (write _test-input-stream "  index a, 0\n")
 7865     (write _test-input-stream "}\n")
 7866     # convert
 7867     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7868     # registers except esp clobbered at this point
 7869     # restore ed
 7870     89/<- %edx 4/r32/esp
 7871     (flush _test-output-buffered-file)
 7872     (flush _test-error-buffered-file)
 7873 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7879     # check output
 7880     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
 7881     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
 7882     # check that stop(1) was called
 7883     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
 7884     # don't restore from ebp
 7885     81 0/subop/add %esp 8/imm32
 7886     # . epilogue
 7887     5d/pop-to-ebp
 7888     c3/return
 7889 
 7890 test-index-with-too-many-outputs:
 7891     # . prologue
 7892     55/push-ebp
 7893     89/<- %ebp 4/r32/esp
 7894     # setup
 7895     (clear-stream _test-input-stream)
 7896     (clear-stream $_test-input-buffered-file->buffer)
 7897     (clear-stream _test-output-stream)
 7898     (clear-stream $_test-output-buffered-file->buffer)
 7899     (clear-stream _test-error-stream)
 7900     (clear-stream $_test-error-buffered-file->buffer)
 7901     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7902     68/push 0/imm32
 7903     68/push 0/imm32
 7904     89/<- %edx 4/r32/esp
 7905     (tailor-exit-descriptor %edx 0x10)
 7906     #
 7907     (write _test-input-stream "fn foo {\n")
 7908     (write _test-input-stream "  var a: (array int 3)\n")
 7909     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
 7910     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
 7911     (write _test-input-stream "  b, c <- index a, 0\n")
 7912     (write _test-input-stream "}\n")
 7913     # convert
 7914     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7915     # registers except esp clobbered at this point
 7916     # restore ed
 7917     89/<- %edx 4/r32/esp
 7918     (flush _test-output-buffered-file)
 7919     (flush _test-error-buffered-file)
 7920 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
 7926     # check output
 7927     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
 7928     (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")
 7929     # check that stop(1) was called
 7930     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
 7931     # don't restore from ebp
 7932     81 0/subop/add %esp 8/imm32
 7933     # . epilogue
 7934     5d/pop-to-ebp
 7935     c3/return
 7936 
 7937 #######################################################
 7938 # Parsing
 7939 #######################################################
 7940 
 7941 == data
 7942 
 7943 # Global state added to each var record when parsing a function
 7944 Next-block-index:  # (addr int)
 7945     1/imm32
 7946 
 7947 Curr-block-depth:  # (addr int)
 7948     1/imm32
 7949 
 7950 == code
 7951 
 7952 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
 7953     # pseudocode
 7954     #   var curr-function: (addr handle function) = Program->functions
 7955     #   var curr-signature: (addr handle function) = Program->signatures
 7956     #   var curr-type: (addr handle typeinfo) = Program->types
 7957     #   var line: (stream byte 512)
 7958     #   var word-slice: slice
 7959     #   while true                                  # line loop
 7960     #     clear-stream(line)
 7961     #     read-line-buffered(in, line)
 7962     #     if (line->write == 0) break               # end of file
 7963     #     word-slice = next-mu-token(line)
 7964     #     if slice-empty?(word-slice)               # end of line
 7965     #       continue
 7966     #     else if slice-starts-with?(word-slice, "#")  # comment
 7967     #       continue                                # end of line
 7968     #     else if slice-equal?(word-slice, "fn")
 7969     #       var new-function: (handle function) = allocate(function)
 7970     #       var vars: (stack live-var 256)
 7971     #       populate-mu-function-header(line, new-function, vars)
 7972     #       populate-mu-function-body(in, new-function, vars)
 7973     #       assert(vars->top == 0)
 7974     #       *curr-function = new-function
 7975     #       curr-function = &new-function->next
 7976     #     else if slice-equal?(word-slice, "sig")
 7977     #       var new-function: (handle function) = allocate(function)
 7978     #       populate-mu-function-signature(line, new-function)
 7979     #       *curr-signature = new-function
 7980     #       curr-signature = &new-function->next
 7981     #     else if slice-equal?(word-slice, "type")
 7982     #       word-slice = next-mu-token(line)
 7983     #       type-id = pos-or-insert-slice(Type-id, word-slice)
 7984     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
 7985     #       assert(next-word(line) == "{")
 7986     #       populate-mu-type(in, new-type)
 7987     #     else
 7988     #       abort()
 7989     #
 7990     # . prologue
 7991     55/push-ebp
 7992     89/<- %ebp 4/r32/esp
 7993     # var curr-signature: (addr handle function) at *(ebp-4)
 7994     68/push _Program-signatures/imm32
 7995     # . save registers
 7996     50/push-eax
 7997     51/push-ecx
 7998     52/push-edx
 7999     53/push-ebx
 8000     56/push-esi
 8001     57/push-edi
 8002     # var line/ecx: (stream byte 512)
 8003     81 5/subop/subtract %esp 0x200/imm32
 8004     68/push 0x200/imm32/size
 8005     68/push 0/imm32/read
 8006     68/push 0/imm32/write
 8007     89/<- %ecx 4/r32/esp
 8008     # var word-slice/edx: slice
 8009     68/push 0/imm32/end
 8010     68/push 0/imm32/start
 8011     89/<- %edx 4/r32/esp
 8012     # var curr-function/edi: (addr handle function)
 8013     bf/copy-to-edi _Program-functions/imm32
 8014     # var vars/ebx: (stack live-var 256)
 8015     81 5/subop/subtract %esp 0xc00/imm32
 8016     68/push 0xc00/imm32/size
 8017     68/push 0/imm32/top
 8018     89/<- %ebx 4/r32/esp
 8019     {
 8020 $parse-mu:line-loop:
 8021       (clear-stream %ecx)
 8022       (read-line-buffered *(ebp+8) %ecx)
 8023       # if (line->write == 0) break
 8024       81 7/subop/compare *ecx 0/imm32
 8025       0f 84/jump-if-= break/disp32
 8026 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
 8032       (next-mu-token %ecx %edx)
 8033       # if slice-empty?(word-slice) continue
 8034       (slice-empty? %edx)  # => eax
 8035       3d/compare-eax-and 0/imm32/false
 8036       0f 85/jump-if-!= loop/disp32
 8037       # if (*word-slice->start == "#") continue
 8038       # . eax = *word-slice->start
 8039       8b/-> *edx 0/r32/eax
 8040       8a/copy-byte *eax 0/r32/AL
 8041       81 4/subop/and %eax 0xff/imm32
 8042       # . if (eax == '#') continue
 8043       3d/compare-eax-and 0x23/imm32/hash
 8044       0f 84/jump-if-= loop/disp32
 8045       # if (slice-equal?(word-slice, "fn")) parse a function
 8046       {
 8047 $parse-mu:fn:
 8048         (slice-equal? %edx "fn")  # => eax
 8049         3d/compare-eax-and 0/imm32/false
 8050         0f 84/jump-if-= break/disp32
 8051         # var new-function/esi: (handle function)
 8052         68/push 0/imm32
 8053         68/push 0/imm32
 8054         89/<- %esi 4/r32/esp
 8055         # populate-mu-function(line, in, vars, new-function)
 8056         (allocate Heap *Function-size %esi)
 8057         # var new-function-addr/eax: (addr function)
 8058         (lookup *esi *(esi+4))  # => eax
 8059         # initialize vars
 8060         (clear-stack %ebx)
 8061         #
 8062         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
 8063         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
 8064         # *curr-function = new-function
 8065         8b/-> *esi 0/r32/eax
 8066         89/<- *edi 0/r32/eax
 8067         8b/-> *(esi+4) 0/r32/eax
 8068         89/<- *(edi+4) 0/r32/eax
 8069         # curr-function = &new-function->next
 8070         # . var tmp/eax: (addr function) = lookup(new-function)
 8071         (lookup *esi *(esi+4))  # => eax
 8072         # . curr-function = &tmp->next
 8073         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
 8074         # reclaim new-function
 8075         81 0/subop/add %esp 8/imm32
 8076         #
 8077         e9/jump $parse-mu:line-loop/disp32
 8078       }
 8079       # if (slice-equal?(word-slice, "sig")) parse a function signature
 8080       # Function signatures are for providing types to SubX functions.
 8081       {
 8082 $parse-mu:sig:
 8083         (slice-equal? %edx "sig")  # => eax
 8084         3d/compare-eax-and 0/imm32/false
 8085         0f 84/jump-if-= break/disp32
 8086         # edi = curr-function
 8087         57/push-edi
 8088         8b/-> *(ebp-4) 7/r32/edi
 8089         # var new-function/esi: (handle function)
 8090         68/push 0/imm32
 8091         68/push 0/imm32
 8092         89/<- %esi 4/r32/esp
 8093         # populate-mu-function(line, in, vars, new-function)
 8094         (allocate Heap *Function-size %esi)
 8095         # var new-function-addr/eax: (addr function)
 8096         (lookup *esi *(esi+4))  # => eax
 8097         #
 8098         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
 8099         # *curr-signature = new-function
 8100         8b/-> *esi 0/r32/eax
 8101         89/<- *edi 0/r32/eax
 8102         8b/-> *(esi+4) 0/r32/eax
 8103         89/<- *(edi+4) 0/r32/eax
 8104         # curr-signature = &new-function->next
 8105         # . var tmp/eax: (addr function) = lookup(new-function)
 8106         (lookup *esi *(esi+4))  # => eax
 8107         # . curr-function = &tmp->next
 8108         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
 8109         # reclaim new-function
 8110         81 0/subop/add %esp 8/imm32
 8111         # save curr-function
 8112         89/<- *(ebp-4) 7/r32/edi
 8113         # restore edi
 8114         5f/pop-to-edi
 8115         #
 8116         e9/jump $parse-mu:line-loop/disp32
 8117       }
 8118       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
 8119       {
 8120 $parse-mu:type:
 8121         (slice-equal? %edx "type")  # => eax
 8122         3d/compare-eax-and 0/imm32
 8123         0f 84/jump-if-= break/disp32
 8124         (next-mu-token %ecx %edx)
 8125         # var type-id/eax: int
 8126         (pos-or-insert-slice Type-id %edx)  # => eax
 8127         # spill
 8128         51/push-ecx
 8129         # var new-type/ecx: (handle typeinfo)
 8130         68/push 0/imm32
 8131         68/push 0/imm32
 8132         89/<- %ecx 4/r32/esp
 8133         (find-or-create-typeinfo %eax %ecx)
 8134         #
 8135         (lookup *ecx *(ecx+4))  # => eax
 8136         # TODO: ensure that 'line' has nothing else but '{'
 8137 #? (dump-typeinfos "=== aaa\n")
 8138         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
 8139 #? (dump-typeinfos "=== zzz\n")
 8140         # reclaim new-type
 8141         81 0/subop/add %esp 8/imm32
 8142         # restore
 8143         59/pop-to-ecx
 8144         e9/jump $parse-mu:line-loop/disp32
 8145       }
 8146       # otherwise abort
 8147       e9/jump $parse-mu:error1/disp32
 8148     } # end line loop
 8149 $parse-mu:end:
 8150     # . reclaim locals
 8151     81 0/subop/add %esp 0x20c/imm32  # line
 8152     81 0/subop/add %esp 0xc08/imm32  # vars
 8153     81 0/subop/add %esp 8/imm32
 8154     # . restore registers
 8155     5f/pop-to-edi
 8156     5e/pop-to-esi
 8157     5b/pop-to-ebx
 8158     5a/pop-to-edx
 8159     59/pop-to-ecx
 8160     58/pop-to-eax
 8161     # . reclaim local
 8162     81 0/subop/add %esp 4/imm32
 8163     # . epilogue
 8164     89/<- %esp 5/r32/ebp
 8165     5d/pop-to-ebp
 8166     c3/return
 8167 
 8168 $parse-mu:error1:
 8169     # error("unexpected top-level command: " word-slice "\n")
 8170     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
 8171     (write-slice-buffered *(ebp+0xc) %edx)
 8172     (write-buffered *(ebp+0xc) "\n")
 8173     (flush *(ebp+0xc))
 8174     (stop *(ebp+0x10) 1)
 8175     # never gets here
 8176 
 8177 $parse-mu:error2:
 8178     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
 8179     (write-int32-hex-buffered *(ebp+0xc) *ebx)
 8180     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
 8181     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
 8182     (write-buffered *(ebp+0xc) "'\n")
 8183     (flush *(ebp+0xc))
 8184     (stop *(ebp+0x10) 1)
 8185     # never gets here
 8186 
 8187 # scenarios considered:
 8188 # ✗ fn foo  # no block
 8189 # ✓ fn foo {
 8190 # ✗ fn foo { {
 8191 # ✗ fn foo { }
 8192 # ✗ fn foo { } {
 8193 # ✗ fn foo x {
 8194 # ✗ fn foo x: {
 8195 # ✓ fn foo x: int {
 8196 # ✓ fn foo x: int {
 8197 # ✓ fn foo x: int -> y/eax: int {
 8198 # TODO:
 8199 #   disallow outputs of type `(... addr ...)`
 8200 #   disallow inputs of type `(... addr ... addr ...)`
 8201 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)
 8202     # pseudocode:
 8203     #   var word-slice: slice
 8204     #   next-mu-token(first-line, word-slice)
 8205     #   if slice-empty?(word-slice) abort
 8206     #   assert(word-slice not in '{' '}' '->')
 8207     #   out->name = slice-to-string(word-slice)
 8208     #   ## inouts
 8209     #   while true
 8210     #     word-slice = next-mu-token(first-line)
 8211     #     if slice-empty?(word-slice) abort
 8212     #     if (word-slice == '{') goto done
 8213     #     if (word-slice == '->') break
 8214     #     assert(word-slice != '}')
 8215     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
 8216     #     assert(v->register == null)
 8217     #     # v->block-depth is implicitly 0
 8218     #     out->inouts = append(v, out->inouts)
 8219     #     push(vars, {v, false})
 8220     #   ## outputs
 8221     #   while true
 8222     #     word-slice = next-mu-token(first-line)
 8223     #     if slice-empty?(word-slice) abort
 8224     #     if (word-slice == '{') break
 8225     #     assert(word-slice not in '}' '->')
 8226     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
 8227     #     assert(v->register != null)
 8228     #     out->outputs = append(v, out->outputs)
 8229     #   done:
 8230     #
 8231     # . prologue
 8232     55/push-ebp
 8233     89/<- %ebp 4/r32/esp
 8234     # . save registers
 8235     50/push-eax
 8236     51/push-ecx
 8237     52/push-edx
 8238     53/push-ebx
 8239     57/push-edi
 8240     # edi = out
 8241     8b/-> *(ebp+0xc) 7/r32/edi
 8242     # var word-slice/ecx: slice
 8243     68/push 0/imm32/end
 8244     68/push 0/imm32/start
 8245     89/<- %ecx 4/r32/esp
 8246     # var v/ebx: (handle var)
 8247     68/push 0/imm32
 8248     68/push 0/imm32
 8249     89/<- %ebx 4/r32/esp
 8250     # read function name
 8251     (next-mu-token *(ebp+8) %ecx)
 8252     # error checking
 8253     # if slice-empty?(word-slice) abort
 8254     (slice-empty? %ecx)  # => eax
 8255     3d/compare-eax-and 0/imm32/false
 8256     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8257     # if (word-slice == '{') abort
 8258     (slice-equal? %ecx "{")   # => eax
 8259     3d/compare-eax-and 0/imm32/false
 8260     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8261     # if (word-slice == '->') abort
 8262     (slice-equal? %ecx "->")   # => eax
 8263     3d/compare-eax-and 0/imm32/false
 8264     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8265     # if (word-slice == '}') abort
 8266     (slice-equal? %ecx "}")   # => eax
 8267     3d/compare-eax-and 0/imm32/false
 8268     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8269     # save function name
 8270     (slice-to-string Heap %ecx %edi)  # Function-name
 8271     # save function inouts
 8272     {
 8273 $populate-mu-function-header:check-for-inout:
 8274       (next-mu-token *(ebp+8) %ecx)
 8275       # if slice-empty?(word-slice) abort
 8276       (slice-empty? %ecx)  # => eax
 8277       3d/compare-eax-and 0/imm32/false
 8278       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8279       # if (word-slice == '{') goto done
 8280       (slice-equal? %ecx "{")   # => eax
 8281       3d/compare-eax-and 0/imm32/false
 8282       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
 8283       # if (word-slice == '->') break
 8284       (slice-equal? %ecx "->")   # => eax
 8285       3d/compare-eax-and 0/imm32/false
 8286       0f 85/jump-if-!= break/disp32
 8287       # if (word-slice == '}') abort
 8288       (slice-equal? %ecx "}")   # => eax
 8289       3d/compare-eax-and 0/imm32/false
 8290       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8291       # v = parse-var-with-type(word-slice, first-line)
 8292       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
 8293       # assert(v->register == null)
 8294       # . eax: (addr var) = lookup(v)
 8295       (lookup *ebx *(ebx+4))  # => eax
 8296       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
 8297       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
 8298       # v->block-depth is implicitly 0
 8299       #
 8300       # out->inouts = append(v, out->inouts)
 8301       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
 8302       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
 8303       # push(vars, {v, false})
 8304       (push *(ebp+0x10) *ebx)
 8305       (push *(ebp+0x10) *(ebx+4))
 8306       (push *(ebp+0x10) 0)  # false
 8307       #
 8308       e9/jump loop/disp32
 8309     }
 8310     # save function outputs
 8311     {
 8312 $populate-mu-function-header:check-for-out:
 8313       (next-mu-token *(ebp+8) %ecx)
 8314       # if slice-empty?(word-slice) abort
 8315       (slice-empty? %ecx)  # => eax
 8316       3d/compare-eax-and 0/imm32/false
 8317       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8318       # if (word-slice == '{') break
 8319       (slice-equal? %ecx "{")   # => eax
 8320       3d/compare-eax-and 0/imm32/false
 8321       0f 85/jump-if-!= break/disp32
 8322       # if (word-slice == '->') abort
 8323       (slice-equal? %ecx "->")   # => eax
 8324       3d/compare-eax-and 0/imm32/false
 8325       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8326       # if (word-slice == '}') abort
 8327       (slice-equal? %ecx "}")   # => eax
 8328       3d/compare-eax-and 0/imm32/false
 8329       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
 8330       # v = parse-var-with-type(word-slice, first-line)
 8331       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18))
 8332       # assert(var->register != null)
 8333       # . eax: (addr var) = lookup(v)
 8334       (lookup *ebx *(ebx+4))  # => eax
 8335       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
 8336       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
 8337       # out->outputs = append(v, out->outputs)
 8338       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
 8339       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
 8340       #
 8341       e9/jump loop/disp32
 8342     }
 8343 $populate-mu-function-header:done:
 8344     (check-no-tokens-left *(ebp+8))
 8345 $populate-mu-function-header:end:
 8346     # . reclaim locals
 8347     81 0/subop/add %esp 0x10/imm32
 8348     # . restore registers
 8349     5f/pop-to-edi
 8350     5b/pop-to-ebx
 8351     5a/pop-to-edx
 8352     59/pop-to-ecx
 8353     58/pop-to-eax
 8354     # . epilogue
 8355     89/<- %esp 5/r32/ebp
 8356     5d/pop-to-ebp
 8357     c3/return
 8358 
 8359 $populate-mu-function-header:error1:
 8360     # error("function header not in form 'fn <name> {'")
 8361     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
 8362     (flush *(ebp+0x14))
 8363     (rewind-stream *(ebp+8))
 8364     (write-stream-data *(ebp+0x14) *(ebp+8))
 8365     (write-buffered *(ebp+0x14) "'\n")
 8366     (flush *(ebp+0x14))
 8367     (stop *(ebp+0x18) 1)
 8368     # never gets here
 8369 
 8370 $populate-mu-function-header:error2:
 8371     # error("fn " fn ": function inout '" var "' cannot be in a register")
 8372     (write-buffered *(ebp+0x14) "fn ")
 8373     50/push-eax
 8374     (lookup *edi *(edi+4))  # Function-name Function-name => eax
 8375     (write-buffered *(ebp+0x14) %eax)
 8376     58/pop-to-eax
 8377     (write-buffered *(ebp+0x14) ": function inout '")
 8378     (lookup *eax *(eax+4))  # Var-name Var-name => eax
 8379     (write-buffered *(ebp+0x10) %eax)
 8380     (write-buffered *(ebp+0x14) "' cannot be in a register")
 8381     (flush *(ebp+0x14))
 8382     (stop *(ebp+0x18) 1)
 8383     # never gets here
 8384 
 8385 $populate-mu-function-header:error3:
 8386     # error("fn " fn ": function output '" var "' must be in a register")
 8387     (write-buffered *(ebp+0x14) "fn ")
 8388     50/push-eax
 8389     (lookup *edi *(edi+4))  # Function-name Function-name => eax
 8390     (write-buffered *(ebp+0x14) %eax)
 8391     58/pop-to-eax
 8392     (write-buffered *(ebp+0x14) ": function output '")
 8393     (lookup *ebx *(ebx+4))  # => eax
 8394     (lookup *eax *(eax+4))  # Var-name Var-name => eax
 8395     (write-buffered *(ebp+0x14) %eax)
 8396     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
 8397     (rewind-stream *(ebp+8))
 8398     (write-stream-data *(ebp+0x14) *(ebp+8))
 8399     (write-buffered *(ebp+0x14) "'\n")
 8400     (flush *(ebp+0x14))
 8401     (stop *(ebp+0x18) 1)
 8402     # never gets here
 8403 
 8404 # scenarios considered:
 8405 # ✓ fn foo
 8406 # ✗ fn foo {
 8407 # ✓ fn foo x
 8408 # ✓ fn foo x: int
 8409 # ✓ fn foo x: int -> y/eax: int
 8410 # TODO:
 8411 #   disallow outputs of type `(... addr ...)`
 8412 #   disallow inputs of type `(... addr ... addr ...)`
 8413 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
 8414     # pseudocode:
 8415     #   var word-slice: slice
 8416     #   next-mu-token(first-line, word-slice)
 8417     #   assert(word-slice not in '{' '}' '->')
 8418     #   out->name = slice-to-string(word-slice)
 8419     #   ## inouts
 8420     #   while true
 8421     #     word-slice = next-mu-token(first-line)
 8422     #     if slice-empty?(word-slice) break
 8423     #     if (word-slice == '->') break
 8424     #     assert(word-slice not in '{' '}')
 8425     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
 8426     #     assert(v->register == null)
 8427     #     # v->block-depth is implicitly 0
 8428     #     out->inouts = append(v, out->inouts)
 8429     #   ## outputs
 8430     #   while true
 8431     #     word-slice = next-mu-token(first-line)
 8432     #     if slice-empty?(word-slice) break
 8433     #     assert(word-slice not in '{' '}' '->')
 8434     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
 8435     #     assert(v->register != null)
 8436     #     out->outputs = append(v, out->outputs)
 8437     #
 8438     # . prologue
 8439     55/push-ebp
 8440     89/<- %ebp 4/r32/esp
 8441     # . save registers
 8442     50/push-eax
 8443     51/push-ecx
 8444     52/push-edx
 8445     53/push-ebx
 8446     57/push-edi
 8447     # edi = out
 8448     8b/-> *(ebp+0xc) 7/r32/edi
 8449     # var word-slice/ecx: slice
 8450     68/push 0/imm32/end
 8451     68/push 0/imm32/start
 8452     89/<- %ecx 4/r32/esp
 8453     # var v/ebx: (handle var)
 8454     68/push 0/imm32
 8455     68/push 0/imm32
 8456     89/<- %ebx 4/r32/esp
 8457     # read function name
 8458     (next-mu-token *(ebp+8) %ecx)
 8459     # error checking
 8460     # if (word-slice == '{') abort
 8461     (slice-equal? %ecx "{")   # => eax
 8462     3d/compare-eax-and 0/imm32/false
 8463     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8464     # if (word-slice == '->') abort
 8465     (slice-equal? %ecx "->")   # => eax
 8466     3d/compare-eax-and 0/imm32/false
 8467     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8468     # if (word-slice == '}') abort
 8469     (slice-equal? %ecx "}")   # => eax
 8470     3d/compare-eax-and 0/imm32/false
 8471     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8472     # save function name
 8473     (slice-to-string Heap %ecx %edi)  # Function-name
 8474     # save function inouts
 8475     {
 8476 $populate-mu-function-signature:check-for-inout:
 8477       (next-mu-token *(ebp+8) %ecx)
 8478       (slice-empty? %ecx)  # => eax
 8479       3d/compare-eax-and 0/imm32/false
 8480       0f 85/jump-if-!= break/disp32
 8481       # if (word-slice == '->') break
 8482       (slice-equal? %ecx "->")   # => eax
 8483       3d/compare-eax-and 0/imm32/false
 8484       0f 85/jump-if-!= break/disp32
 8485       # if (word-slice == '{') abort
 8486       (slice-equal? %ecx "{")   # => eax
 8487       3d/compare-eax-and 0/imm32/false
 8488       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8489       # if (word-slice == '}') abort
 8490       (slice-equal? %ecx "}")   # => eax
 8491       3d/compare-eax-and 0/imm32/false
 8492       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8493       # v = parse-var-with-type(word-slice, first-line)
 8494       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
 8495       # assert(v->register == null)
 8496       # . eax: (addr var) = lookup(v)
 8497       (lookup *ebx *(ebx+4))  # => eax
 8498       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
 8499       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
 8500       # v->block-depth is implicitly 0
 8501       #
 8502       # out->inouts = append(v, out->inouts)
 8503       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
 8504       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
 8505       #
 8506       e9/jump loop/disp32
 8507     }
 8508     # save function outputs
 8509     {
 8510 $populate-mu-function-signature:check-for-out:
 8511       (next-mu-token *(ebp+8) %ecx)
 8512       (slice-empty? %ecx)  # => eax
 8513       3d/compare-eax-and 0/imm32/false
 8514       0f 85/jump-if-!= break/disp32
 8515       # if (word-slice == '{') abort
 8516       (slice-equal? %ecx "{")   # => eax
 8517       3d/compare-eax-and 0/imm32/false
 8518       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8519       # if (word-slice == '->') abort
 8520       (slice-equal? %ecx "->")   # => eax
 8521       3d/compare-eax-and 0/imm32/false
 8522       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8523       # if (word-slice == '}') abort
 8524       (slice-equal? %ecx "}")   # => eax
 8525       3d/compare-eax-and 0/imm32/false
 8526       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
 8527       # v = parse-var-with-type(word-slice, first-line)
 8528       (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x10) *(ebp+0x14))
 8529       # assert(var->register != null)
 8530       # . eax: (addr var) = lookup(v)
 8531       (lookup *ebx *(ebx+4))  # => eax
 8532       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
 8533       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
 8534       # out->outputs = append(v, out->outputs)
 8535       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
 8536       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
 8537       #
 8538       e9/jump loop/disp32
 8539     }
 8540 $populate-mu-function-signature:done:
 8541     (check-no-tokens-left *(ebp+8))
 8542 $populate-mu-function-signature:end:
 8543     # . reclaim locals
 8544     81 0/subop/add %esp 0x10/imm32
 8545     # . restore registers
 8546     5f/pop-to-edi
 8547     5b/pop-to-ebx
 8548     5a/pop-to-edx
 8549     59/pop-to-ecx
 8550     58/pop-to-eax
 8551     # . epilogue
 8552     89/<- %esp 5/r32/ebp
 8553     5d/pop-to-ebp
 8554     c3/return
 8555 
 8556 $populate-mu-function-signature:error1:
 8557     # error("function signature not in form 'fn <name> {'")
 8558     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
 8559     (flush *(ebp+0x10))
 8560     (rewind-stream *(ebp+8))
 8561     (write-stream-data *(ebp+0x10) *(ebp+8))
 8562     (write-buffered *(ebp+0x10) "'\n")
 8563     (flush *(ebp+0x10))
 8564     (stop *(ebp+0x14) 1)
 8565     # never gets here
 8566 
 8567 $populate-mu-function-signature:error2:
 8568     # error("fn " fn ": function inout '" var "' cannot be in a register")
 8569     (write-buffered *(ebp+0x10) "fn ")
 8570     50/push-eax
 8571     (lookup *edi *(edi+4))  # Function-name Function-name => eax
 8572     (write-buffered *(ebp+0x10) %eax)
 8573     58/pop-to-eax
 8574     (write-buffered *(ebp+0x10) ": function inout '")
 8575     (lookup *eax *(eax+4))  # Var-name Var-name => eax
 8576     (write-buffered *(ebp+0x10) %eax)
 8577     (write-buffered *(ebp+0x10) "' cannot be in a register")
 8578     (flush *(ebp+0x10))
 8579     (stop *(ebp+0x14) 1)
 8580     # never gets here
 8581 
 8582 $populate-mu-function-signature:error3:
 8583     # error("fn " fn ": function output '" var "' must be in a register")
 8584     (write-buffered *(ebp+0x10) "fn ")
 8585     50/push-eax
 8586     (lookup *edi *(edi+4))  # Function-name Function-name => eax
 8587     (write-buffered *(ebp+0x10) %eax)
 8588     58/pop-to-eax
 8589     (write-buffered *(ebp+0x10) ": function output '")
 8590     (lookup *ebx *(ebx+4))  # => eax
 8591     (lookup *eax *(eax+4))  # Var-name Var-name => eax
 8592     (write-buffered *(ebp+0x10) %eax)
 8593     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
 8594     (rewind-stream *(ebp+8))
 8595     (write-stream-data *(ebp+0x10) *(ebp+8))
 8596     (write-buffered *(ebp+0x10) "'\n")
 8597     (flush *(ebp+0x10))
 8598     (stop *(ebp+0x14) 1)
 8599     # never gets here
 8600 
 8601 test-function-header-with-arg:
 8602     # . prologue
 8603     55/push-ebp
 8604     89/<- %ebp 4/r32/esp
 8605     # setup
 8606     8b/-> *Primitive-type-ids 0/r32/eax
 8607     89/<- *Type-id 0/r32/eax  # stream-write
 8608     (clear-stream _test-input-stream)
 8609     (write _test-input-stream "foo n: int {\n")
 8610     # var result/ecx: function
 8611     2b/subtract *Function-size 4/r32/esp
 8612     89/<- %ecx 4/r32/esp
 8613     (zero-out %ecx *Function-size)
 8614     # var vars/ebx: (stack live-var 16)
 8615     81 5/subop/subtract %esp 0xc0/imm32
 8616     68/push 0xc0/imm32/size
 8617     68/push 0/imm32/top
 8618     89/<- %ebx 4/r32/esp
 8619     # convert
 8620     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
 8621     # check result->name
 8622     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
 8623     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
 8624     # var v/edx: (addr var) = result->inouts->value
 8625     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
 8626     (lookup *eax *(eax+4))  # List-value List-value => eax
 8627     89/<- %edx 0/r32/eax
 8628     # check v->name
 8629     (lookup *edx *(edx+4))  # Var-name Var-name => eax
 8630     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
 8631     # check v->type
 8632     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
 8633     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
 8634     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
 8635     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
 8636     # . epilogue
 8637     89/<- %esp 5/r32/ebp
 8638     5d/pop-to-ebp
 8639     c3/return
 8640 
 8641 test-function-header-with-multiple-args:
 8642     # . prologue
 8643     55/push-ebp
 8644     89/<- %ebp 4/r32/esp
 8645     # setup
 8646     8b/-> *Primitive-type-ids 0/r32/eax
 8647     89/<- *Type-id 0/r32/eax  # stream-write
 8648     (clear-stream _test-input-stream)
 8649     (write _test-input-stream "foo a: int, b: int c: int {\n")
 8650     # result/ecx: function
 8651     2b/subtract *Function-size 4/r32/esp
 8652     89/<- %ecx 4/r32/esp
 8653     (zero-out %ecx *Function-size)
 8654     # var vars/ebx: (stack live-var 16)
 8655     81 5/subop/subtract %esp 0xc0/imm32
 8656     68/push 0xc0/imm32/size
 8657     68/push 0/imm32/top
 8658     89/<- %ebx 4/r32/esp
 8659     # convert
 8660     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
 8661     # check result->name
 8662     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
 8663     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
 8664     # var inouts/edx: (addr list var) = lookup(result->inouts)
 8665     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
 8666     89/<- %edx 0/r32/eax
 8667 $test-function-header-with-multiple-args:inout0:
 8668     # var v/ebx: (addr var) = lookup(inouts->value)
 8669     (lookup *edx *(edx+4))  # List-value List-value => eax
 8670     89/<- %ebx 0/r32/eax
 8671     # check v->name
 8672     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8673     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
 8674     # check v->type
 8675     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8676     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
 8677     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
 8678     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
 8679 $test-function-header-with-multiple-args:inout1:
 8680     # inouts = lookup(inouts->next)
 8681     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
 8682     89/<- %edx 0/r32/eax
 8683     # v = lookup(inouts->value)
 8684     (lookup *edx *(edx+4))  # List-value List-value => eax
 8685     89/<- %ebx 0/r32/eax
 8686     # check v->name
 8687     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8688     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
 8689     # check v->type
 8690     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8691     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
 8692     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
 8693     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
 8694 $test-function-header-with-multiple-args:inout2:
 8695     # inouts = lookup(inouts->next)
 8696     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
 8697     89/<- %edx 0/r32/eax
 8698     # v = lookup(inouts->value)
 8699     (lookup *edx *(edx+4))  # List-value List-value => eax
 8700     89/<- %ebx 0/r32/eax
 8701     # check v->name
 8702     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8703     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
 8704     # check v->type
 8705     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8706     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
 8707     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
 8708     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
 8709     # . epilogue
 8710     89/<- %esp 5/r32/ebp
 8711     5d/pop-to-ebp
 8712     c3/return
 8713 
 8714 test-function-header-with-multiple-args-and-outputs:
 8715     # . prologue
 8716     55/push-ebp
 8717     89/<- %ebp 4/r32/esp
 8718     # setup
 8719     8b/-> *Primitive-type-ids 0/r32/eax
 8720     89/<- *Type-id 0/r32/eax  # stream-write
 8721     (clear-stream _test-input-stream)
 8722     (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n")
 8723     # result/ecx: function
 8724     2b/subtract *Function-size 4/r32/esp
 8725     89/<- %ecx 4/r32/esp
 8726     (zero-out %ecx *Function-size)
 8727     # var vars/ebx: (stack live-var 16)
 8728     81 5/subop/subtract %esp 0xc0/imm32
 8729     68/push 0xc0/imm32/size
 8730     68/push 0/imm32/top
 8731     89/<- %ebx 4/r32/esp
 8732     # convert
 8733     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
 8734     # check result->name
 8735     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
 8736     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
 8737     # var inouts/edx: (addr list var) = lookup(result->inouts)
 8738     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
 8739     89/<- %edx 0/r32/eax
 8740 $test-function-header-with-multiple-args-and-outputs:inout0:
 8741     # var v/ebx: (addr var) = lookup(inouts->value)
 8742     (lookup *edx *(edx+4))  # List-value List-value => eax
 8743     89/<- %ebx 0/r32/eax
 8744     # check v->name
 8745     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8746     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
 8747     # check v->type
 8748     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8749     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
 8750     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
 8751     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
 8752 $test-function-header-with-multiple-args-and-outputs:inout1:
 8753     # inouts = lookup(inouts->next)
 8754     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
 8755     89/<- %edx 0/r32/eax
 8756     # v = lookup(inouts->value)
 8757     (lookup *edx *(edx+4))  # List-value List-value => eax
 8758     89/<- %ebx 0/r32/eax
 8759     # check v->name
 8760     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8761     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
 8762     # check v->type
 8763     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8764     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
 8765     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
 8766     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
 8767 $test-function-header-with-multiple-args-and-outputs:inout2:
 8768     # inouts = lookup(inouts->next)
 8769     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
 8770     89/<- %edx 0/r32/eax
 8771     # v = lookup(inouts->value)
 8772     (lookup *edx *(edx+4))  # List-value List-value => eax
 8773     89/<- %ebx 0/r32/eax
 8774     # check v->name
 8775     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8776     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
 8777     # check v->type
 8778     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8779     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
 8780     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
 8781     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
 8782 $test-function-header-with-multiple-args-and-outputs:out0:
 8783     # var outputs/edx: (addr list var) = lookup(result->outputs)
 8784     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
 8785     89/<- %edx 0/r32/eax
 8786     # v = lookup(outputs->value)
 8787     (lookup *edx *(edx+4))  # List-value List-value => eax
 8788     89/<- %ebx 0/r32/eax
 8789     # check v->name
 8790     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8791     (check-strings-equal %eax "x" "F - test-function-header-with-multiple-args-and-outputs/output:0")
 8792     # check v->register
 8793     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
 8794     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
 8795     # check v->type
 8796     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8797     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
 8798     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
 8799     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
 8800 $test-function-header-with-multiple-args-and-outputs:out1:
 8801     # outputs = lookup(outputs->next)
 8802     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
 8803     89/<- %edx 0/r32/eax
 8804     # v = lookup(inouts->value)
 8805     (lookup *edx *(edx+4))  # List-value List-value => eax
 8806     89/<- %ebx 0/r32/eax
 8807     # check v->name
 8808     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
 8809     (check-strings-equal %eax "y" "F - test-function-header-with-multiple-args-and-outputs/output:1")
 8810     # check v->register
 8811     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
 8812     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
 8813     # check v->type
 8814     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
 8815     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
 8816     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
 8817     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
 8818     # . epilogue
 8819     89/<- %esp 5/r32/ebp
 8820     5d/pop-to-ebp
 8821     c3/return
 8822 
 8823 # format for variables with types
 8824 #   x: int
 8825 #   x: int,
 8826 #   x/eax: int
 8827 #   x/eax: int,
 8828 # ignores at most one trailing comma
 8829 # WARNING: modifies name
 8830 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
 8831     # pseudocode:
 8832     #   var s: slice
 8833     #   if (!slice-ends-with(name, ":"))
 8834     #     abort
 8835     #   --name->end to skip ':'
 8836     #   next-token-from-slice(name->start, name->end, '/', s)
 8837     #   new-var-from-slice(s, out)
 8838     #   ## register
 8839     #   next-token-from-slice(s->end, name->end, '/', s)
 8840     #   if (!slice-empty?(s))
 8841     #     out->register = slice-to-string(s)
 8842     #   ## type
 8843     #   var type: (handle type-tree) = parse-type(first-line)
 8844     #   out->type = type
 8845     #
 8846     # . prologue
 8847     55/push-ebp
 8848     89/<- %ebp 4/r32/esp
 8849     # . save registers
 8850     50/push-eax
 8851     51/push-ecx
 8852     52/push-edx
 8853     53/push-ebx
 8854     56/push-esi
 8855     57/push-edi
 8856     # esi = name
 8857     8b/-> *(ebp+8) 6/r32/esi
 8858     # if (!slice-ends-with?(name, ":")) abort
 8859     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
 8860     49/decrement-ecx
 8861     8a/copy-byte *ecx 1/r32/CL
 8862     81 4/subop/and %ecx 0xff/imm32
 8863     81 7/subop/compare %ecx 0x3a/imm32/colon
 8864     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
 8865     # --name->end to skip ':'
 8866     ff 1/subop/decrement *(esi+4)
 8867     # var s/ecx: slice
 8868     68/push 0/imm32/end
 8869     68/push 0/imm32/start
 8870     89/<- %ecx 4/r32/esp
 8871 $parse-var-with-type:parse-name:
 8872     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
 8873 $parse-var-with-type:create-var:
 8874     # new-var-from-slice(s, out)
 8875     (new-var-from-slice Heap %ecx *(ebp+0x10))
 8876     # save out->register
 8877 $parse-var-with-type:save-register:
 8878     # . var out-addr/edi: (addr var) = lookup(*out)
 8879     8b/-> *(ebp+0x10) 7/r32/edi
 8880     (lookup *edi *(edi+4))  # => eax
 8881     89/<- %edi 0/r32/eax
 8882     # . s = next-token(...)
 8883     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
 8884     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
 8885     {
 8886 $parse-var-with-type:write-register:
 8887       (slice-empty? %ecx)  # => eax
 8888       3d/compare-eax-and 0/imm32/false
 8889       75/jump-if-!= break/disp8
 8890       # out->register = slice-to-string(s)
 8891       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
 8892       (slice-to-string Heap %ecx %eax)
 8893     }
 8894 $parse-var-with-type:save-type:
 8895     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
 8896     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
 8897 $parse-var-with-type:end:
 8898     # . reclaim locals
 8899     81 0/subop/add %esp 8/imm32
 8900     # . restore registers
 8901     5f/pop-to-edi
 8902     5e/pop-to-esi
 8903     5b/pop-to-ebx
 8904     5a/pop-to-edx
 8905     59/pop-to-ecx
 8906     58/pop-to-eax
 8907     # . epilogue
 8908     89/<- %esp 5/r32/ebp
 8909     5d/pop-to-ebp
 8910     c3/return
 8911 
 8912 $parse-var-with-type:abort:
 8913     # error("var should have form 'name: type' in '" line "'\n")
 8914     (write-buffered *(ebp+0x14) "var should have form 'name: type' in '")
 8915     (flush *(ebp+0x14))
 8916     (rewind-stream *(ebp+0xc))
 8917     (write-stream-data *(ebp+0x14) *(ebp+0xc))
 8918     (write-buffered *(ebp+0x14) "'\n")
 8919     (flush *(ebp+0x14))
 8920     (stop *(ebp+0x18) 1)
 8921     # never gets here
 8922 
 8923 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
 8924     # pseudocode:
 8925     #   var s: slice = next-mu-token(in)
 8926     #   assert s != ""
 8927     #   assert s != "->"
 8928     #   assert s != "{"
 8929     #   assert s != "}"
 8930     #   if s == ")"
 8931     #     return
 8932     #   out = allocate(Type-tree)
 8933     #   if s != "("
 8934     #     HACK: if s is an int, parse and return it
 8935     #     out->is-atom? = true
 8936     #     if (s[0] == "_")
 8937     #       out->value = type-parameter
 8938     #       out->parameter-name = slice-to-string(ad, s)
 8939     #     else
 8940     #       out->value = pos-or-insert-slice(Type-id, s)
 8941     #     return
 8942     #   out->left = parse-type(ad, in)
 8943     #   out->right = parse-type-tree(ad, in)
 8944     #
 8945     # . prologue
 8946     55/push-ebp
 8947     89/<- %ebp 4/r32/esp
 8948     # . save registers
 8949     50/push-eax
 8950     51/push-ecx
 8951     52/push-edx
 8952     # clear out
 8953     (zero-out *(ebp+0x10) *Handle-size)
 8954     # var s/ecx: slice
 8955     68/push 0/imm32
 8956     68/push 0/imm32
 8957     89/<- %ecx 4/r32/esp
 8958     # s = next-mu-token(in)
 8959     (next-mu-token *(ebp+0xc) %ecx)
 8960 #?     (write-buffered Stderr "tok: ")
 8961 #?     (write-slice-buffered Stderr %ecx)
 8962 #?     (write-buffered Stderr "$\n")
 8963 #?     (flush Stderr)
 8964     # assert s != ""
 8965     (slice-equal? %ecx "")  # => eax
 8966     3d/compare-eax-and 0/imm32/false
 8967     0f 85/jump-if-!= $parse-type:abort/disp32
 8968     # assert s != "{"
 8969     (slice-equal? %ecx "{")  # => eax
 8970     3d/compare-eax-and 0/imm32/false
 8971     0f 85/jump-if-!= $parse-type:abort/disp32
 8972     # assert s != "}"
 8973     (slice-equal? %ecx "}")  # => eax
 8974     3d/compare-eax-and 0/imm32/false
 8975     0f 85/jump-if-!= $parse-type:abort/disp32
 8976     # assert s != "->"
 8977     (slice-equal? %ecx "->")  # => eax
 8978     3d/compare-eax-and 0/imm32/false
 8979     0f 85/jump-if-!= $parse-type:abort/disp32
 8980     # if (s == ")") return
 8981     (slice-equal? %ecx ")")  # => eax
 8982     3d/compare-eax-and 0/imm32/false
 8983     0f 85/jump-if-!= $parse-type:end/disp32
 8984     # out = new tree
 8985     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
 8986     # var out-addr/edx: (addr type-tree) = lookup(*out)
 8987     8b/-> *(ebp+0x10) 2/r32/edx
 8988     (lookup *edx *(edx+4))  # => eax
 8989     89/<- %edx 0/r32/eax
 8990     {
 8991       # if (s != "(") break
 8992       (slice-equal? %ecx "(")  # => eax
 8993       3d/compare-eax-and 0/imm32/false
 8994       0f 85/jump-if-!= break/disp32
 8995       # if s is a number, store it in the type's size field
 8996       {
 8997 $parse-type:check-for-int:
 8998         # var tmp/eax: byte = *s->slice
 8999         8b/-> *ecx 0/r32/eax
 9000         8a/copy-byte *eax 0/r32/AL
 9001         81 4/subop/and %eax 0xff/imm32
 9002         # TODO: raise an error on `var x: (array int a)`
 9003         (is-decimal-digit? %eax)  # => eax
 9004         3d/compare-eax-and 0/imm32/false
 9005         74/jump-if-= break/disp8
 9006         #
 9007         (is-hex-int? %ecx)  # => eax
 9008         3d/compare-eax-and 0/imm32/false
 9009         74/jump-if-= break/disp8
 9010 $parse-type:int:
 9011         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
 9012         (parse-hex-int-from-slice %ecx)  # => eax
 9013         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
 9014         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
 9015         e9/jump $parse-type:end/disp32
 9016       }
 9017 $parse-type:atom:
 9018       # out->is-atom? = true
 9019       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
 9020       {
 9021 $parse-type:check-for-type-parameter:
 9022         # var tmp/eax: byte = *s->slice
 9023         8b/-> *ecx 0/r32/eax
 9024         8a/copy-byte *eax 0/r32/AL
 9025         81 4/subop/and %eax 0xff/imm32
 9026         # if (tmp != '_') break
 9027         3d/compare-eax-and 0x5f/imm32/_
 9028         75/jump-if-!= break/disp8
 9029 $parse-type:type-parameter:
 9030         # out->value = type-parameter
 9031         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
 9032         # out->parameter-name = slice-to-string(ad, s)
 9033         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
 9034         (slice-to-string *(ebp+8) %ecx %eax)
 9035         e9/jump $parse-type:end/disp32
 9036       }
 9037 $parse-type:non-type-parameter:
 9038       # out->value = pos-or-insert-slice(Type-id, s)
 9039       (pos-or-insert-slice Type-id %ecx)  # => eax
 9040       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
 9041       e9/jump $parse-type:end/disp32
 9042     }
 9043 $parse-type:non-atom:
 9044     # otherwise s == "("
 9045     # out->left = parse-type(ad, in)
 9046     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
 9047     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
 9048     # out->right = parse-type-tree(ad, in)
 9049     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
 9050     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
 9051 $parse-type:end:
 9052     # . reclaim locals
 9053     81 0/subop/add %esp 8/imm32
 9054     # . restore registers
 9055     5a/pop-to-edx
 9056     59/pop-to-ecx
 9057     58/pop-to-eax
 9058     # . epilogue
 9059     89/<- %esp 5/r32/ebp
 9060     5d/pop-to-ebp
 9061     c3/return
 9062 
 9063 $parse-type:abort:
 9064     # error("unexpected token when parsing type: '" s "'\n")
 9065     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
 9066     (write-slice-buffered *(ebp+0x14) %ecx)
 9067     (write-buffered *(ebp+0x14) "'\n")
 9068     (flush *(ebp+0x14))
 9069     (stop *(ebp+0x18) 1)
 9070     # never gets here
 9071 
 9072 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
 9073     # pseudocode:
 9074     #   var tmp: (handle type-tree) = parse-type(ad, in)
 9075     #   if tmp == 0
 9076     #     return 0
 9077     #   out = allocate(Type-tree)
 9078     #   out->left = tmp
 9079     #   out->right = parse-type-tree(ad, in)
 9080     #
 9081     # . prologue
 9082     55/push-ebp
 9083     89/<- %ebp 4/r32/esp
 9084     # . save registers
 9085     50/push-eax
 9086     51/push-ecx
 9087     52/push-edx
 9088     #
 9089     (zero-out *(ebp+0x10) *Handle-size)
 9090     # var tmp/ecx: (handle type-tree)
 9091     68/push 0/imm32
 9092     68/push 0/imm32
 9093     89/<- %ecx 4/r32/esp
 9094     # tmp = parse-type(ad, in)
 9095     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
 9096     # if (tmp == 0) return
 9097     81 7/subop/compare *ecx 0/imm32
 9098     74/jump-if-= $parse-type-tree:end/disp8
 9099     # out = new tree
 9100     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
 9101     # var out-addr/edx: (addr tree) = lookup(*out)
 9102     8b/-> *(ebp+0x10) 2/r32/edx
 9103     (lookup *edx *(edx+4))  # => eax
 9104     89/<- %edx 0/r32/eax
 9105     # out->left = tmp
 9106     8b/-> *ecx 0/r32/eax
 9107     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
 9108     8b/-> *(ecx+4) 0/r32/eax
 9109     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
 9110     # out->right = parse-type-tree(ad, in)
 9111     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
 9112     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
 9113 $parse-type-tree:end:
 9114     # . reclaim locals
 9115     81 0/subop/add %esp 8/imm32
 9116     # . restore registers
 9117     5a/pop-to-edx
 9118     59/pop-to-ecx
 9119     58/pop-to-eax
 9120     # . epilogue
 9121     89/<- %esp 5/r32/ebp
 9122     5d/pop-to-ebp
 9123     c3/return
 9124 
 9125 next-mu-token:  # in: (addr stream byte), out: (addr slice)
 9126     # pseudocode:
 9127     # start:
 9128     #   skip-chars-matching-whitespace(in)
 9129     #   if in->read >= in->write              # end of in
 9130     #     out = {0, 0}
 9131     #     return
 9132     #   out->start = &in->data[in->read]
 9133     #   var curr-byte/eax: byte = in->data[in->read]
 9134     #   if curr->byte == ','                  # comment token
 9135     #     ++in->read
 9136     #     goto start
 9137     #   if curr-byte == '#'                   # comment
 9138     #     goto done                             # treat as eof
 9139     #   if curr-byte == '"'                   # string literal
 9140     #     skip-string(in)
 9141     #     goto done                           # no metadata
 9142     #   if curr-byte == '('
 9143     #     ++in->read
 9144     #     goto done
 9145     #   if curr-byte == ')'
 9146     #     ++in->read
 9147     #     goto done
 9148     #   # read a word
 9149     #   while true
 9150     #     if in->read >= in->write
 9151     #       break
 9152     #     curr-byte = in->data[in->read]
 9153     #     if curr-byte == ' '
 9154     #       break
 9155     #     if curr-byte == '\r'
 9156     #       break
 9157     #     if curr-byte == '\n'
 9158     #       break
 9159     #     if curr-byte == '('
 9160     #       break
 9161     #     if curr-byte == ')'
 9162     #       break
 9163     #     if curr-byte == ','
 9164     #       break
 9165     #     ++in->read
 9166     # done:
 9167     #   out->end = &in->data[in->read]
 9168     #
 9169     # . prologue
 9170     55/push-ebp
 9171     89/<- %ebp 4/r32/esp
 9172     # . save registers
 9173     50/push-eax
 9174     51/push-ecx
 9175     56/push-esi
 9176     57/push-edi
 9177     # esi = in
 9178     8b/-> *(ebp+8) 6/r32/esi
 9179     # edi = out
 9180     8b/-> *(ebp+0xc) 7/r32/edi
 9181 $next-mu-token:start:
 9182     (skip-chars-matching-whitespace %esi)
 9183 $next-mu-token:check0:
 9184     # if (in->read >= in->write) return out = {0, 0}
 9185     # . ecx = in->read
 9186     8b/-> *(esi+4) 1/r32/ecx
 9187     # . if (ecx >= in->write) return out = {0, 0}
 9188     3b/compare<- *esi 1/r32/ecx
 9189     c7 0/subop/copy *edi 0/imm32
 9190     c7 0/subop/copy *(edi+4) 0/imm32
 9191     0f 8d/jump-if->= $next-mu-token:end/disp32
 9192     # out->start = &in->data[in->read]
 9193     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
 9194     89/<- *edi 0/r32/eax
 9195     # var curr-byte/eax: byte = in->data[in->read]
 9196     31/xor-with %eax 0/r32/eax
 9197     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
 9198     {
 9199 $next-mu-token:check-for-comma:
 9200       # if (curr-byte != ',') break
 9201       3d/compare-eax-and 0x2c/imm32/comma
 9202       75/jump-if-!= break/disp8
 9203       # ++in->read
 9204       ff 0/subop/increment *(esi+4)
 9205       # restart
 9206       e9/jump $next-mu-token:start/disp32
 9207     }
 9208     {
 9209 $next-mu-token:check-for-comment:
 9210       # if (curr-byte != '#') break
 9211       3d/compare-eax-and 0x23/imm32/pound
 9212       75/jump-if-!= break/disp8
 9213       # return eof
 9214       e9/jump $next-mu-token:done/disp32
 9215     }
 9216     {
 9217 $next-mu-token:check-for-string-literal:
 9218       # if (curr-byte != '"') break
 9219       3d/compare-eax-and 0x22/imm32/dquote
 9220       75/jump-if-!= break/disp8
 9221       (skip-string %esi)
 9222       # return
 9223       e9/jump $next-mu-token:done/disp32
 9224     }
 9225     {
 9226 $next-mu-token:check-for-open-paren:
 9227       # if (curr-byte != '(') break
 9228       3d/compare-eax-and 0x28/imm32/open-paren
 9229       75/jump-if-!= break/disp8
 9230       # ++in->read
 9231       ff 0/subop/increment *(esi+4)
 9232       # return
 9233       e9/jump $next-mu-token:done/disp32
 9234     }
 9235     {
 9236 $next-mu-token:check-for-close-paren:
 9237       # if (curr-byte != ')') break
 9238       3d/compare-eax-and 0x29/imm32/close-paren
 9239       75/jump-if-!= break/disp8
 9240       # ++in->read
 9241       ff 0/subop/increment *(esi+4)
 9242       # return
 9243       e9/jump $next-mu-token:done/disp32
 9244     }
 9245     {
 9246 $next-mu-token:regular-word-without-metadata:
 9247       # if (in->read >= in->write) break
 9248       # . ecx = in->read
 9249       8b/-> *(esi+4) 1/r32/ecx
 9250       # . if (ecx >= in->write) break
 9251       3b/compare<- *esi 1/r32/ecx
 9252       7d/jump-if->= break/disp8
 9253       # var c/eax: byte = in->data[in->read]
 9254       31/xor-with %eax 0/r32/eax
 9255       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
 9256       # if (c == ' ') break
 9257       3d/compare-eax-and 0x20/imm32/space
 9258       74/jump-if-= break/disp8
 9259       # if (c == '\r') break
 9260       3d/compare-eax-and 0xd/imm32/carriage-return
 9261       74/jump-if-= break/disp8
 9262       # if (c == '\n') break
 9263       3d/compare-eax-and 0xa/imm32/newline
 9264       74/jump-if-= break/disp8
 9265       # if (c == '(') break
 9266       3d/compare-eax-and 0x28/imm32/open-paren
 9267       0f 84/jump-if-= break/disp32
 9268       # if (c == ')') break
 9269       3d/compare-eax-and 0x29/imm32/close-paren
 9270       0f 84/jump-if-= break/disp32
 9271       # if (c == ',') break
 9272       3d/compare-eax-and 0x2c/imm32/comma
 9273       0f 84/jump-if-= break/disp32
 9274       # ++in->read
 9275       ff 0/subop/increment *(esi+4)
 9276       #
 9277       e9/jump loop/disp32
 9278     }
 9279 $next-mu-token:done:
 9280     # out->end = &in->data[in->read]
 9281     8b/-> *(esi+4) 1/r32/ecx
 9282     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
 9283     89/<- *(edi+4) 0/r32/eax
 9284 $next-mu-token:end:
 9285     # . restore registers
 9286     5f/pop-to-edi
 9287     5e/pop-to-esi
 9288     59/pop-to-ecx
 9289     58/pop-to-eax
 9290     # . epilogue
 9291     89/<- %esp 5/r32/ebp
 9292     5d/pop-to-ebp
 9293     c3/return
 9294 
 9295 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
 9296     # . prologue
 9297     55/push-ebp
 9298     89/<- %ebp 4/r32/esp
 9299     # if (pos-slice(arr, s) != -1) return it
 9300     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
 9301     3d/compare-eax-and -1/imm32
 9302     75/jump-if-!= $pos-or-insert-slice:end/disp8
 9303 $pos-or-insert-slice:insert:
 9304     # var s2/eax: (handle array byte)
 9305     68/push 0/imm32
 9306     68/push 0/imm32
 9307     89/<- %eax 4/r32/esp
 9308     (slice-to-string Heap *(ebp+0xc) %eax)
 9309     # throw away alloc-id
 9310     (lookup *eax *(eax+4))  # => eax
 9311     (write-int *(ebp+8) %eax)
 9312     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
 9313 $pos-or-insert-slice:end:
 9314     # . reclaim locals
 9315     81 0/subop/add %esp 8/imm32
 9316     # . epilogue
 9317     89/<- %esp 5/r32/ebp
 9318     5d/pop-to-ebp
 9319     c3/return
 9320 
 9321 # return the index in an array of strings matching 's', -1 if not found
 9322 # index is denominated in elements, not bytes
 9323 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
 9324     # . prologue
 9325     55/push-ebp
 9326     89/<- %ebp 4/r32/esp
 9327     # . save registers
 9328     51/push-ecx
 9329     52/push-edx
 9330     53/push-ebx
 9331     56/push-esi
 9332 #?     (write-buffered Stderr "pos-slice: ")
 9333 #?     (write-slice-buffered Stderr *(ebp+0xc))
 9334 #?     (write-buffered Stderr "\n")
 9335 #?     (flush Stderr)
 9336     # esi = arr
 9337     8b/-> *(ebp+8) 6/r32/esi
 9338     # var index/ecx: int = 0
 9339     b9/copy-to-ecx 0/imm32
 9340     # var curr/edx: (addr (addr array byte)) = arr->data
 9341     8d/copy-address *(esi+0xc) 2/r32/edx
 9342     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
 9343     8b/-> *esi 3/r32/ebx
 9344     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
 9345     {
 9346 #?       (write-buffered Stderr "  ")
 9347 #?       (write-int32-hex-buffered Stderr %ecx)
 9348 #?       (write-buffered Stderr "\n")
 9349 #?       (flush Stderr)
 9350       # if (curr >= max) return -1
 9351       39/compare %edx 3/r32/ebx
 9352       b8/copy-to-eax -1/imm32
 9353       73/jump-if-addr>= $pos-slice:end/disp8
 9354       # if (slice-equal?(s, *curr)) break
 9355       (slice-equal? *(ebp+0xc) *edx)  # => eax
 9356       3d/compare-eax-and 0/imm32/false
 9357       75/jump-if-!= break/disp8
 9358       # ++index
 9359       41/increment-ecx
 9360       # curr += 4
 9361       81 0/subop/add %edx 4/imm32
 9362       #
 9363       eb/jump loop/disp8
 9364     }
 9365     # return index
 9366     89/<- %eax 1/r32/ecx
 9367 $pos-slice:end:
 9368 #?     (write-buffered Stderr "=> ")
 9369 #?     (write-int32-hex-buffered Stderr %eax)
 9370 #?     (write-buffered Stderr "\n")
 9371     # . restore registers
 9372     5e/pop-to-esi
 9373     5b/pop-to-ebx
 9374     5a/pop-to-edx
 9375     59/pop-to-ecx
 9376     # . epilogue
 9377     89/<- %esp 5/r32/ebp
 9378     5d/pop-to-ebp
 9379     c3/return
 9380 
 9381 test-parse-var-with-type:
 9382     # . prologue
 9383     55/push-ebp
 9384     89/<- %ebp 4/r32/esp
 9385     # setup
 9386     8b/-> *Primitive-type-ids 0/r32/eax
 9387     89/<- *Type-id 0/r32/eax  # stream-write
 9388     # (eax..ecx) = "x:"
 9389     b8/copy-to-eax "x:"/imm32
 9390     8b/-> *eax 1/r32/ecx
 9391     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9392     05/add-to-eax 4/imm32
 9393     # var slice/ecx: slice = {eax, ecx}
 9394     51/push-ecx
 9395     50/push-eax
 9396     89/<- %ecx 4/r32/esp
 9397     # _test-input-stream contains "int"
 9398     (clear-stream _test-input-stream)
 9399     (write _test-input-stream "int")
 9400     # var v/edx: (handle var)
 9401     68/push 0/imm32
 9402     68/push 0/imm32
 9403     89/<- %edx 4/r32/esp
 9404     #
 9405     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
 9406     # var v-addr/edx: (addr var) = lookup(v)
 9407     (lookup *edx *(edx+4))  # => eax
 9408     89/<- %edx 0/r32/eax
 9409     # check v-addr->name
 9410     (lookup *edx *(edx+4))  # Var-name Var-name => eax
 9411     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
 9412     # check v-addr->type
 9413     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
 9414     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
 9415     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
 9416     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
 9417     # . epilogue
 9418     89/<- %esp 5/r32/ebp
 9419     5d/pop-to-ebp
 9420     c3/return
 9421 
 9422 test-parse-var-with-type-and-register:
 9423     # . prologue
 9424     55/push-ebp
 9425     89/<- %ebp 4/r32/esp
 9426     # setup
 9427     8b/-> *Primitive-type-ids 0/r32/eax
 9428     89/<- *Type-id 0/r32/eax  # stream-write
 9429     # (eax..ecx) = "x/eax:"
 9430     b8/copy-to-eax "x/eax:"/imm32
 9431     8b/-> *eax 1/r32/ecx
 9432     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9433     05/add-to-eax 4/imm32
 9434     # var slice/ecx: slice = {eax, ecx}
 9435     51/push-ecx
 9436     50/push-eax
 9437     89/<- %ecx 4/r32/esp
 9438     # _test-input-stream contains "int"
 9439     (clear-stream _test-input-stream)
 9440     (write _test-input-stream "int")
 9441     # var v/edx: (handle var)
 9442     68/push 0/imm32
 9443     68/push 0/imm32
 9444     89/<- %edx 4/r32/esp
 9445     #
 9446     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
 9447     # var v-addr/edx: (addr var) = lookup(v)
 9448     (lookup *edx *(edx+4))  # => eax
 9449     89/<- %edx 0/r32/eax
 9450     # check v-addr->name
 9451     (lookup *edx *(edx+4))  # Var-name Var-name => eax
 9452     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
 9453     # check v-addr->register
 9454     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
 9455     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
 9456     # check v-addr->type
 9457     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
 9458     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
 9459     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
 9460     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
 9461     # . epilogue
 9462     89/<- %esp 5/r32/ebp
 9463     5d/pop-to-ebp
 9464     c3/return
 9465 
 9466 test-parse-var-with-trailing-characters:
 9467     # . prologue
 9468     55/push-ebp
 9469     89/<- %ebp 4/r32/esp
 9470     # setup
 9471     8b/-> *Primitive-type-ids 0/r32/eax
 9472     89/<- *Type-id 0/r32/eax  # stream-write
 9473     # (eax..ecx) = "x:"
 9474     b8/copy-to-eax "x:"/imm32
 9475     8b/-> *eax 1/r32/ecx
 9476     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9477     05/add-to-eax 4/imm32
 9478     # var slice/ecx: slice = {eax, ecx}
 9479     51/push-ecx
 9480     50/push-eax
 9481     89/<- %ecx 4/r32/esp
 9482     # _test-input-stream contains "int,"
 9483     (clear-stream _test-input-stream)
 9484     (write _test-input-stream "int,")
 9485     # var v/edx: (handle var)
 9486     68/push 0/imm32
 9487     68/push 0/imm32
 9488     89/<- %edx 4/r32/esp
 9489     #
 9490     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
 9491     # var v-addr/edx: (addr var) = lookup(v)
 9492     (lookup *edx *(edx+4))  # => eax
 9493     89/<- %edx 0/r32/eax
 9494     # check v-addr->name
 9495     (lookup *edx *(edx+4))  # Var-name Var-name => eax
 9496     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
 9497     # check v-addr->register
 9498     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
 9499     # check v-addr->type
 9500     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
 9501     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
 9502     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
 9503     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
 9504     # . epilogue
 9505     89/<- %esp 5/r32/ebp
 9506     5d/pop-to-ebp
 9507     c3/return
 9508 
 9509 test-parse-var-with-register-and-trailing-characters:
 9510     # . prologue
 9511     55/push-ebp
 9512     89/<- %ebp 4/r32/esp
 9513     # setup
 9514     8b/-> *Primitive-type-ids 0/r32/eax
 9515     89/<- *Type-id 0/r32/eax  # stream-write
 9516     # (eax..ecx) = "x/eax:"
 9517     b8/copy-to-eax "x/eax:"/imm32
 9518     8b/-> *eax 1/r32/ecx
 9519     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9520     05/add-to-eax 4/imm32
 9521     # var slice/ecx: slice = {eax, ecx}
 9522     51/push-ecx
 9523     50/push-eax
 9524     89/<- %ecx 4/r32/esp
 9525     # _test-input-stream contains "int,"
 9526     (clear-stream _test-input-stream)
 9527     (write _test-input-stream "int,")
 9528     # var v/edx: (handle var)
 9529     68/push 0/imm32
 9530     68/push 0/imm32
 9531     89/<- %edx 4/r32/esp
 9532     #
 9533     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
 9534     # var v-addr/edx: (addr var) = lookup(v)
 9535     (lookup *edx *(edx+4))  # => eax
 9536     89/<- %edx 0/r32/eax
 9537     # check v-addr->name
 9538     (lookup *edx *(edx+4))  # Var-name Var-name => eax
 9539     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
 9540     # check v-addr->register
 9541     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
 9542     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
 9543     # check v-addr->type
 9544     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
 9545     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
 9546     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
 9547     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
 9548     # . epilogue
 9549     89/<- %esp 5/r32/ebp
 9550     5d/pop-to-ebp
 9551     c3/return
 9552 
 9553 test-parse-var-with-compound-type:
 9554     # . prologue
 9555     55/push-ebp
 9556     89/<- %ebp 4/r32/esp
 9557     # setup
 9558     8b/-> *Primitive-type-ids 0/r32/eax
 9559     89/<- *Type-id 0/r32/eax  # stream-write
 9560     # (eax..ecx) = "x:"
 9561     b8/copy-to-eax "x:"/imm32
 9562     8b/-> *eax 1/r32/ecx
 9563     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9564     05/add-to-eax 4/imm32
 9565     # var slice/ecx: slice = {eax, ecx}
 9566     51/push-ecx
 9567     50/push-eax
 9568     89/<- %ecx 4/r32/esp
 9569     # _test-input-stream contains "(addr int)"
 9570     (clear-stream _test-input-stream)
 9571     (write _test-input-stream "(addr int)")
 9572     # var v/edx: (handle var)
 9573     68/push 0/imm32
 9574     68/push 0/imm32
 9575     89/<- %edx 4/r32/esp
 9576     #
 9577     (parse-var-with-type %ecx _test-input-stream %edx Stderr 0)
 9578     # var v-addr/edx: (addr var) = lookup(v)
 9579     (lookup *edx *(edx+4))  # => eax
 9580     89/<- %edx 0/r32/eax
 9581     # check v-addr->name
 9582     (lookup *edx *(edx+4))  # Var-name Var-name => eax
 9583     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
 9584     # check v-addr->register
 9585     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
 9586     # - check v-addr->type
 9587     # var type/edx: (addr type-tree) = var->type
 9588     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
 9589     89/<- %edx 0/r32/eax
 9590     # type is a non-atom
 9591     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
 9592     # type->left == atom(addr)
 9593     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
 9594     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
 9595     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
 9596     # type->right->left == atom(int)
 9597     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
 9598     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
 9599     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
 9600     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
 9601     # type->right->right == null
 9602     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
 9603     # . epilogue
 9604     89/<- %esp 5/r32/ebp
 9605     5d/pop-to-ebp
 9606     c3/return
 9607 
 9608 # identifier starts with a letter or '$' or '_'
 9609 # no constraints at the moment on later letters
 9610 # all we really want to do so far is exclude '{', '}' and '->'
 9611 is-identifier?:  # in: (addr slice) -> result/eax: boolean
 9612     # . prologue
 9613     55/push-ebp
 9614     89/<- %ebp 4/r32/esp
 9615     # if (slice-empty?(in)) return false
 9616     (slice-empty? *(ebp+8))  # => eax
 9617     3d/compare-eax-and 0/imm32/false
 9618     75/jump-if-!= $is-identifier?:false/disp8
 9619     # var c/eax: byte = *in->start
 9620     8b/-> *(ebp+8) 0/r32/eax
 9621     8b/-> *eax 0/r32/eax
 9622     8a/copy-byte *eax 0/r32/AL
 9623     81 4/subop/and %eax 0xff/imm32
 9624     # if (c == '$') return true
 9625     3d/compare-eax-and 0x24/imm32/$
 9626     74/jump-if-= $is-identifier?:true/disp8
 9627     # if (c == '_') return true
 9628     3d/compare-eax-and 0x5f/imm32/_
 9629     74/jump-if-= $is-identifier?:true/disp8
 9630     # drop case
 9631     25/and-eax-with 0x5f/imm32
 9632     # if (c < 'A') return false
 9633     3d/compare-eax-and 0x41/imm32/A
 9634     7c/jump-if-< $is-identifier?:false/disp8
 9635     # if (c > 'Z') return false
 9636     3d/compare-eax-and 0x5a/imm32/Z
 9637     7f/jump-if-> $is-identifier?:false/disp8
 9638     # otherwise return true
 9639 $is-identifier?:true:
 9640     b8/copy-to-eax 1/imm32/true
 9641     eb/jump $is-identifier?:end/disp8
 9642 $is-identifier?:false:
 9643     b8/copy-to-eax 0/imm32/false
 9644 $is-identifier?:end:
 9645     # . epilogue
 9646     89/<- %esp 5/r32/ebp
 9647     5d/pop-to-ebp
 9648     c3/return
 9649 
 9650 test-is-identifier-dollar:
 9651     # . prologue
 9652     55/push-ebp
 9653     89/<- %ebp 4/r32/esp
 9654     # (eax..ecx) = "$a"
 9655     b8/copy-to-eax "$a"/imm32
 9656     8b/-> *eax 1/r32/ecx
 9657     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9658     05/add-to-eax 4/imm32
 9659     # var slice/ecx: slice = {eax, ecx}
 9660     51/push-ecx
 9661     50/push-eax
 9662     89/<- %ecx 4/r32/esp
 9663     #
 9664     (is-identifier? %ecx)
 9665     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
 9666     # . epilogue
 9667     89/<- %esp 5/r32/ebp
 9668     5d/pop-to-ebp
 9669     c3/return
 9670 
 9671 test-is-identifier-underscore:
 9672     # . prologue
 9673     55/push-ebp
 9674     89/<- %ebp 4/r32/esp
 9675     # (eax..ecx) = "_a"
 9676     b8/copy-to-eax "_a"/imm32
 9677     8b/-> *eax 1/r32/ecx
 9678     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9679     05/add-to-eax 4/imm32
 9680     # var slice/ecx: slice = {eax, ecx}
 9681     51/push-ecx
 9682     50/push-eax
 9683     89/<- %ecx 4/r32/esp
 9684     #
 9685     (is-identifier? %ecx)
 9686     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
 9687     # . epilogue
 9688     89/<- %esp 5/r32/ebp
 9689     5d/pop-to-ebp
 9690     c3/return
 9691 
 9692 test-is-identifier-a:
 9693     # . prologue
 9694     55/push-ebp
 9695     89/<- %ebp 4/r32/esp
 9696     # (eax..ecx) = "a$"
 9697     b8/copy-to-eax "a$"/imm32
 9698     8b/-> *eax 1/r32/ecx
 9699     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9700     05/add-to-eax 4/imm32
 9701     # var slice/ecx: slice = {eax, ecx}
 9702     51/push-ecx
 9703     50/push-eax
 9704     89/<- %ecx 4/r32/esp
 9705     #
 9706     (is-identifier? %ecx)
 9707     (check-ints-equal %eax 1 "F - test-is-identifier-a")
 9708     # . epilogue
 9709     89/<- %esp 5/r32/ebp
 9710     5d/pop-to-ebp
 9711     c3/return
 9712 
 9713 test-is-identifier-z:
 9714     # . prologue
 9715     55/push-ebp
 9716     89/<- %ebp 4/r32/esp
 9717     # (eax..ecx) = "z$"
 9718     b8/copy-to-eax "z$"/imm32
 9719     8b/-> *eax 1/r32/ecx
 9720     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9721     05/add-to-eax 4/imm32
 9722     # var slice/ecx: slice = {eax, ecx}
 9723     51/push-ecx
 9724     50/push-eax
 9725     89/<- %ecx 4/r32/esp
 9726     #
 9727     (is-identifier? %ecx)
 9728     (check-ints-equal %eax 1 "F - test-is-identifier-z")
 9729     # . epilogue
 9730     89/<- %esp 5/r32/ebp
 9731     5d/pop-to-ebp
 9732     c3/return
 9733 
 9734 test-is-identifier-A:
 9735     # . prologue
 9736     55/push-ebp
 9737     89/<- %ebp 4/r32/esp
 9738     # (eax..ecx) = "A$"
 9739     b8/copy-to-eax "A$"/imm32
 9740     8b/-> *eax 1/r32/ecx
 9741     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9742     05/add-to-eax 4/imm32
 9743     # var slice/ecx: slice = {eax, ecx}
 9744     51/push-ecx
 9745     50/push-eax
 9746     89/<- %ecx 4/r32/esp
 9747     #
 9748     (is-identifier? %ecx)
 9749     (check-ints-equal %eax 1 "F - test-is-identifier-A")
 9750     # . epilogue
 9751     89/<- %esp 5/r32/ebp
 9752     5d/pop-to-ebp
 9753     c3/return
 9754 
 9755 test-is-identifier-Z:
 9756     # . prologue
 9757     55/push-ebp
 9758     89/<- %ebp 4/r32/esp
 9759     # (eax..ecx) = "Z$"
 9760     b8/copy-to-eax "Z$"/imm32
 9761     8b/-> *eax 1/r32/ecx
 9762     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9763     05/add-to-eax 4/imm32
 9764     # var slice/ecx: slice = {eax, ecx}
 9765     51/push-ecx
 9766     50/push-eax
 9767     89/<- %ecx 4/r32/esp
 9768     #
 9769     (is-identifier? %ecx)
 9770     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
 9771     # . epilogue
 9772     89/<- %esp 5/r32/ebp
 9773     5d/pop-to-ebp
 9774     c3/return
 9775 
 9776 test-is-identifier-at:
 9777     # character before 'A' is invalid
 9778     # . prologue
 9779     55/push-ebp
 9780     89/<- %ebp 4/r32/esp
 9781     # (eax..ecx) = "@a"
 9782     b8/copy-to-eax "@a"/imm32
 9783     8b/-> *eax 1/r32/ecx
 9784     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9785     05/add-to-eax 4/imm32
 9786     # var slice/ecx: slice = {eax, ecx}
 9787     51/push-ecx
 9788     50/push-eax
 9789     89/<- %ecx 4/r32/esp
 9790     #
 9791     (is-identifier? %ecx)
 9792     (check-ints-equal %eax 0 "F - test-is-identifier-@")
 9793     # . epilogue
 9794     89/<- %esp 5/r32/ebp
 9795     5d/pop-to-ebp
 9796     c3/return
 9797 
 9798 test-is-identifier-square-bracket:
 9799     # character after 'Z' is invalid
 9800     # . prologue
 9801     55/push-ebp
 9802     89/<- %ebp 4/r32/esp
 9803     # (eax..ecx) = "[a"
 9804     b8/copy-to-eax "[a"/imm32
 9805     8b/-> *eax 1/r32/ecx
 9806     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9807     05/add-to-eax 4/imm32
 9808     # var slice/ecx: slice = {eax, ecx}
 9809     51/push-ecx
 9810     50/push-eax
 9811     89/<- %ecx 4/r32/esp
 9812     #
 9813     (is-identifier? %ecx)
 9814     (check-ints-equal %eax 0 "F - test-is-identifier-@")
 9815     # . epilogue
 9816     89/<- %esp 5/r32/ebp
 9817     5d/pop-to-ebp
 9818     c3/return
 9819 
 9820 test-is-identifier-backtick:
 9821     # character before 'a' is invalid
 9822     # . prologue
 9823     55/push-ebp
 9824     89/<- %ebp 4/r32/esp
 9825     # (eax..ecx) = "`a"
 9826     b8/copy-to-eax "`a"/imm32
 9827     8b/-> *eax 1/r32/ecx
 9828     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9829     05/add-to-eax 4/imm32
 9830     # var slice/ecx: slice = {eax, ecx}
 9831     51/push-ecx
 9832     50/push-eax
 9833     89/<- %ecx 4/r32/esp
 9834     #
 9835     (is-identifier? %ecx)
 9836     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
 9837     # . epilogue
 9838     89/<- %esp 5/r32/ebp
 9839     5d/pop-to-ebp
 9840     c3/return
 9841 
 9842 test-is-identifier-curly-brace-open:
 9843     # character after 'z' is invalid; also used for blocks
 9844     # . prologue
 9845     55/push-ebp
 9846     89/<- %ebp 4/r32/esp
 9847     # (eax..ecx) = "{a"
 9848     b8/copy-to-eax "{a"/imm32
 9849     8b/-> *eax 1/r32/ecx
 9850     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9851     05/add-to-eax 4/imm32
 9852     # var slice/ecx: slice = {eax, ecx}
 9853     51/push-ecx
 9854     50/push-eax
 9855     89/<- %ecx 4/r32/esp
 9856     #
 9857     (is-identifier? %ecx)
 9858     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
 9859     # . epilogue
 9860     89/<- %esp 5/r32/ebp
 9861     5d/pop-to-ebp
 9862     c3/return
 9863 
 9864 test-is-identifier-curly-brace-close:
 9865     # . prologue
 9866     55/push-ebp
 9867     89/<- %ebp 4/r32/esp
 9868     # (eax..ecx) = "}a"
 9869     b8/copy-to-eax "}a"/imm32
 9870     8b/-> *eax 1/r32/ecx
 9871     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9872     05/add-to-eax 4/imm32
 9873     # var slice/ecx: slice = {eax, ecx}
 9874     51/push-ecx
 9875     50/push-eax
 9876     89/<- %ecx 4/r32/esp
 9877     #
 9878     (is-identifier? %ecx)
 9879     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
 9880     # . epilogue
 9881     89/<- %esp 5/r32/ebp
 9882     5d/pop-to-ebp
 9883     c3/return
 9884 
 9885 test-is-identifier-hyphen:
 9886     # disallow leading '-' since '->' has special meaning
 9887     # . prologue
 9888     55/push-ebp
 9889     89/<- %ebp 4/r32/esp
 9890     # (eax..ecx) = "-a"
 9891     b8/copy-to-eax "-a"/imm32
 9892     8b/-> *eax 1/r32/ecx
 9893     8d/copy-address *(eax+ecx+4) 1/r32/ecx
 9894     05/add-to-eax 4/imm32
 9895     # var slice/ecx: slice = {eax, ecx}
 9896     51/push-ecx
 9897     50/push-eax
 9898     89/<- %ecx 4/r32/esp
 9899     #
 9900     (is-identifier? %ecx)
 9901     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
 9902     # . epilogue
 9903     89/<- %esp 5/r32/ebp
 9904     5d/pop-to-ebp
 9905     c3/return
 9906 
 9907 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
 9908     # . prologue
 9909     55/push-ebp
 9910     89/<- %ebp 4/r32/esp
 9911     # . save registers
 9912     50/push-eax
 9913     56/push-esi
 9914     57/push-edi
 9915     # esi = in
 9916     8b/-> *(ebp+8) 6/r32/esi
 9917     # edi = out
 9918     8b/-> *(ebp+0xc) 7/r32/edi
 9919     # initialize some global state
 9920     c7 0/subop/copy *Curr-block-depth 1/imm32
 9921     # parse-mu-block(in, vars, out, out->body)
 9922     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
 9923     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
 9924 $populate-mu-function-body:end:
 9925     # . restore registers
 9926     5f/pop-to-edi
 9927     5e/pop-to-esi
 9928     58/pop-to-eax
 9929     # . epilogue
 9930     89/<- %esp 5/r32/ebp
 9931     5d/pop-to-ebp
 9932     c3/return
 9933 
 9934 # parses a block, assuming that the leading '{' has already been read by the caller
 9935 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)
 9936     # pseudocode:
 9937     #   var line: (stream byte 512)
 9938     #   var word-slice: slice
 9939     #   allocate(Heap, Stmt-size, out)
 9940     #   var out-addr: (addr block) = lookup(*out)
 9941     #   out-addr->tag = 0/block
 9942     #   out-addr->var = some unique name
 9943     #   push(vars, {out-addr->var, false})
 9944     #   while true                                  # line loop
 9945     #     clear-stream(line)
 9946     #     read-line-buffered(in, line)
 9947     #     if (line->write == 0) break               # end of file
 9948     #     word-slice = next-mu-token(line)
 9949     #     if slice-empty?(word-slice)               # end of line
 9950     #       continue
 9951     #     else if slice-starts-with?(word-slice, "#")
 9952     #       continue
 9953     #     else if slice-equal?(word-slice, "{")
 9954     #       assert(no-tokens-in(line))
 9955     #       block = parse-mu-block(in, vars, fn)
 9956     #       append-to-block(out-addr, block)
 9957     #     else if slice-equal?(word-slice, "}")
 9958     #       break
 9959     #     else if slice-ends-with?(word-slice, ":")
 9960     #       # TODO: error-check the rest of 'line'
 9961     #       --word-slice->end to skip ':'
 9962     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
 9963     #       append-to-block(out-addr, named-block)
 9964     #     else if slice-equal?(word-slice, "var")
 9965     #       var-def = parse-mu-var-def(line, vars, fn)
 9966     #       append-to-block(out-addr, var-def)
 9967     #     else
 9968     #       stmt = parse-mu-stmt(line, vars, fn)
 9969     #       append-to-block(out-addr, stmt)
 9970     #   pop(vars)
 9971     #
 9972     # . prologue
 9973     55/push-ebp
 9974     89/<- %ebp 4/r32/esp
 9975     # . save registers
 9976     50/push-eax
 9977     51/push-ecx
 9978     52/push-edx
 9979     53/push-ebx
 9980     57/push-edi
 9981     # var line/ecx: (stream byte 512)
 9982     81 5/subop/subtract %esp 0x200/imm32
 9983     68/push 0x200/imm32/size
 9984     68/push 0/imm32/read
 9985     68/push 0/imm32/write
 9986     89/<- %ecx 4/r32/esp
 9987     # var word-slice/edx: slice
 9988     68/push 0/imm32/end
 9989     68/push 0/imm32/start
 9990     89/<- %edx 4/r32/esp
 9991     # allocate into out
 9992     (allocate Heap *Stmt-size *(ebp+0x14))
 9993     # var out-addr/edi: (addr block) = lookup(*out)
 9994     8b/-> *(ebp+0x14) 7/r32/edi
 9995     (lookup *edi *(edi+4))  # => eax
 9996     89/<- %edi 0/r32/eax
 9997     # out-addr->tag is 0 (block) by default
 9998     # set out-addr->var
 9999     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
10000     (new-block-name *(ebp+0x10) %eax)
10001     # push(vars, out-addr->var)
10002     (push *(ebp+0xc) *(edi+0xc))  # Block-var
10003     (push *(ebp+0xc) *(edi+0x10))  # Block-var
10004     (push *(ebp+0xc) 0)  # false
10005     # increment *Curr-block-depth
10006     ff 0/subop/increment *Curr-block-depth
10007     {
10008 $parse-mu-block:line-loop:
10009       # line = read-line-buffered(in)
10010       (clear-stream %ecx)
10011       (read-line-buffered *(ebp+8) %ecx)
10012 #?       (write-buffered Stderr "line: ")
10013 #?       (write-stream-data Stderr %ecx)
10014 #? #?       (write-buffered Stderr Newline)  # line has its own newline
10015 #?       (flush Stderr)
10016 #?       (rewind-stream %ecx)
10017       # if (line->write == 0) break
10018       81 7/subop/compare *ecx 0/imm32
10019       0f 84/jump-if-= break/disp32
10020 #?       (write-buffered Stderr "vars:\n")
10021 #?       (dump-vars *(ebp+0xc))
10022       # word-slice = next-mu-token(line)
10023       (next-mu-token %ecx %edx)
10024 #?       (write-buffered Stderr "word: ")
10025 #?       (write-slice-buffered Stderr %edx)
10026 #?       (write-buffered Stderr Newline)
10027 #?       (flush Stderr)
10028       # if slice-empty?(word-slice) continue
10029       (slice-empty? %edx)
10030       3d/compare-eax-and 0/imm32/false
10031       0f 85/jump-if-!= loop/disp32
10032       # if (slice-starts-with?(word-slice, '#') continue
10033       # . eax = *word-slice->start
10034       8b/-> *edx 0/r32/eax
10035       8a/copy-byte *eax 0/r32/AL
10036       81 4/subop/and %eax 0xff/imm32
10037       # . if (eax == '#') continue
10038       3d/compare-eax-and 0x23/imm32/hash
10039       0f 84/jump-if-= loop/disp32
10040       # if slice-equal?(word-slice, "{")
10041       {
10042 $parse-mu-block:check-for-block:
10043         (slice-equal? %edx "{")
10044         3d/compare-eax-and 0/imm32/false
10045         74/jump-if-= break/disp8
10046         (check-no-tokens-left %ecx)
10047         # parse new block and append
10048         # . var tmp/eax: (handle block)
10049         68/push 0/imm32
10050         68/push 0/imm32
10051         89/<- %eax 4/r32/esp
10052         # .
10053         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
10054         (append-to-block Heap %edi  *eax *(eax+4))
10055         # . reclaim tmp
10056         81 0/subop/add %esp 8/imm32
10057         # .
10058         e9/jump $parse-mu-block:line-loop/disp32
10059       }
10060       # if slice-equal?(word-slice, "}") break
10061 $parse-mu-block:check-for-end:
10062       (slice-equal? %edx "}")
10063       3d/compare-eax-and 0/imm32/false
10064       0f 85/jump-if-!= break/disp32
10065       # if slice-ends-with?(word-slice, ":") parse named block and append
10066       {
10067 $parse-mu-block:check-for-named-block:
10068         # . eax = *(word-slice->end-1)
10069         8b/-> *(edx+4) 0/r32/eax
10070         48/decrement-eax
10071         8a/copy-byte *eax 0/r32/AL
10072         81 4/subop/and %eax 0xff/imm32
10073         # . if (eax != ':') break
10074         3d/compare-eax-and 0x3a/imm32/colon
10075         0f 85/jump-if-!= break/disp32
10076         # TODO: error-check the rest of 'line'
10077         #
10078         # skip ':'
10079         ff 1/subop/decrement *(edx+4)  # Slice-end
10080         # var tmp/eax: (handle block)
10081         68/push 0/imm32
10082         68/push 0/imm32
10083         89/<- %eax 4/r32/esp
10084         #
10085         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
10086         (append-to-block Heap %edi  *eax *(eax+4))
10087         # reclaim tmp
10088         81 0/subop/add %esp 8/imm32
10089         #
10090         e9/jump $parse-mu-block:line-loop/disp32
10091       }
10092       # if slice-equal?(word-slice, "var")
10093       {
10094 $parse-mu-block:check-for-var:
10095         (slice-equal? %edx "var")
10096         3d/compare-eax-and 0/imm32/false
10097         74/jump-if-= break/disp8
10098         # var tmp/eax: (handle block)
10099         68/push 0/imm32
10100         68/push 0/imm32
10101         89/<- %eax 4/r32/esp
10102         #
10103         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
10104         (append-to-block Heap %edi  *eax *(eax+4))
10105         # reclaim tmp
10106         81 0/subop/add %esp 8/imm32
10107         #
10108         e9/jump $parse-mu-block:line-loop/disp32
10109       }
10110 $parse-mu-block:regular-stmt:
10111       # otherwise
10112       # var tmp/eax: (handle block)
10113       68/push 0/imm32
10114       68/push 0/imm32
10115       89/<- %eax 4/r32/esp
10116       #
10117       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
10118       (append-to-block Heap %edi  *eax *(eax+4))
10119       # reclaim tmp
10120       81 0/subop/add %esp 8/imm32
10121       #
10122       e9/jump loop/disp32
10123     } # end line loop
10124     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
10125     # decrement *Curr-block-depth
10126     ff 1/subop/decrement *Curr-block-depth
10127     # pop(vars)
10128     (pop *(ebp+0xc))  # => eax
10129     (pop *(ebp+0xc))  # => eax
10130     (pop *(ebp+0xc))  # => eax
10131 $parse-mu-block:end:
10132     # . reclaim locals
10133     81 0/subop/add %esp 0x214/imm32
10134     # . restore registers
10135     5f/pop-to-edi
10136     5b/pop-to-ebx
10137     5a/pop-to-edx
10138     59/pop-to-ecx
10139     58/pop-to-eax
10140     # . epilogue
10141     89/<- %esp 5/r32/ebp
10142     5d/pop-to-ebp
10143     c3/return
10144 
10145 $parse-mu-block:abort:
10146     # error("'{' or '}' should be on its own line, but got '")
10147     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
10148     (rewind-stream %ecx)
10149     (write-stream-data *(ebp+0x18) %ecx)
10150     (write-buffered *(ebp+0x18) "'\n")
10151     (flush *(ebp+0x18))
10152     (stop *(ebp+0x1c) 1)
10153     # never gets here
10154 
10155 new-block-name:  # fn: (addr function), out: (addr handle var)
10156     # . prologue
10157     55/push-ebp
10158     89/<- %ebp 4/r32/esp
10159     # . save registers
10160     50/push-eax
10161     51/push-ecx
10162     52/push-edx
10163     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
10164     8b/-> *(ebp+8) 0/r32/eax
10165     (lookup *eax *(eax+4))  # Function-name Function-name => eax
10166     8b/-> *eax 0/r32/eax  # String-size
10167     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
10168     89/<- %ecx 0/r32/eax
10169     # var name/edx: (stream byte n)
10170     29/subtract-from %esp 1/r32/ecx
10171     ff 6/subop/push %ecx
10172     68/push 0/imm32/read
10173     68/push 0/imm32/write
10174     89/<- %edx 4/r32/esp
10175     (clear-stream %edx)
10176     # eax = fn->name
10177     8b/-> *(ebp+8) 0/r32/eax
10178     (lookup *eax *(eax+4))  # Function-name Function-name => eax
10179     # construct result using Next-block-index (and increment it)
10180     (write %edx "$")
10181     (write %edx %eax)
10182     (write %edx ":")
10183     (write-int32-hex %edx *Next-block-index)
10184     ff 0/subop/increment *Next-block-index
10185     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
10186     # . eax = name->write
10187     8b/-> *edx 0/r32/eax
10188     # . edx = name->data
10189     8d/copy-address *(edx+0xc) 2/r32/edx
10190     # . eax = name->write + name->data
10191     01/add-to %eax 2/r32/edx
10192     # . push {edx, eax}
10193     ff 6/subop/push %eax
10194     ff 6/subop/push %edx
10195     89/<- %eax 4/r32/esp
10196     # out = new literal(s)
10197     (new-literal Heap %eax *(ebp+0xc))
10198 #?     8b/-> *(ebp+0xc) 0/r32/eax
10199 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
10200 #?     (write-int32-hex-buffered Stderr *(eax+8))
10201 #?     (write-buffered Stderr " for var ")
10202 #?     (write-int32-hex-buffered Stderr %eax)
10203 #?     (write-buffered Stderr Newline)
10204 #?     (flush Stderr)
10205 $new-block-name:end:
10206     # . reclaim locals
10207     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
10208     81 0/subop/add %ecx 8/imm32  # slice
10209     01/add-to %esp 1/r32/ecx
10210     # . restore registers
10211     5a/pop-to-edx
10212     59/pop-to-ecx
10213     58/pop-to-eax
10214     # . epilogue
10215     89/<- %esp 5/r32/ebp
10216     5d/pop-to-ebp
10217     c3/return
10218 
10219 check-no-tokens-left:  # line: (addr stream byte)
10220     # . prologue
10221     55/push-ebp
10222     89/<- %ebp 4/r32/esp
10223     # . save registers
10224     50/push-eax
10225     51/push-ecx
10226     # var s/ecx: slice
10227     68/push 0/imm32/end
10228     68/push 0/imm32/start
10229     89/<- %ecx 4/r32/esp
10230     #
10231     (next-mu-token *(ebp+8) %ecx)
10232     # if slice-empty?(s) return
10233     (slice-empty? %ecx)
10234     3d/compare-eax-and 0/imm32/false
10235     75/jump-if-!= $check-no-tokens-left:end/disp8
10236     # if (slice-starts-with?(s, '#') return
10237     # . eax = *s->start
10238     8b/-> *edx 0/r32/eax
10239     8a/copy-byte *eax 0/r32/AL
10240     81 4/subop/and %eax 0xff/imm32
10241     # . if (eax == '#') continue
10242     3d/compare-eax-and 0x23/imm32/hash
10243     74/jump-if-= $check-no-tokens-left:end/disp8
10244     # abort
10245     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
10246     (rewind-stream %ecx)
10247     (write-stream 2 %ecx)
10248     (write-buffered Stderr "'\n")
10249     (flush Stderr)
10250     # . syscall(exit, 1)
10251     bb/copy-to-ebx  1/imm32
10252     e8/call syscall_exit/disp32
10253     # never gets here
10254 $check-no-tokens-left:end:
10255     # . reclaim locals
10256     81 0/subop/add %esp 8/imm32
10257     # . restore registers
10258     59/pop-to-ecx
10259     58/pop-to-eax
10260     # . epilogue
10261     89/<- %esp 5/r32/ebp
10262     5d/pop-to-ebp
10263     c3/return
10264 
10265 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)
10266     # pseudocode:
10267     #   var v: (handle var)
10268     #   new-literal(name, v)
10269     #   push(vars, {v, false})
10270     #   parse-mu-block(in, vars, fn, out)
10271     #   pop(vars)
10272     #   out->tag = block
10273     #   out->var = v
10274     #
10275     # . prologue
10276     55/push-ebp
10277     89/<- %ebp 4/r32/esp
10278     # . save registers
10279     50/push-eax
10280     51/push-ecx
10281     57/push-edi
10282     # var v/ecx: (handle var)
10283     68/push 0/imm32
10284     68/push 0/imm32
10285     89/<- %ecx 4/r32/esp
10286     #
10287     (new-literal Heap *(ebp+8) %ecx)
10288     # push(vars, v)
10289     (push *(ebp+0x10) *ecx)
10290     (push *(ebp+0x10) *(ecx+4))
10291     (push *(ebp+0x10) 0)  # false
10292     #
10293     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
10294     # pop v off vars
10295     (pop *(ebp+0x10))  # => eax
10296     (pop *(ebp+0x10))  # => eax
10297     (pop *(ebp+0x10))  # => eax
10298     # var out-addr/edi: (addr stmt) = lookup(*out)
10299     8b/-> *(ebp+0x18) 7/r32/edi
10300     (lookup *edi *(edi+4))  # => eax
10301     89/<- %edi 0/r32/eax
10302     # out-addr->tag = named-block
10303     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
10304     # out-addr->var = v
10305     8b/-> *ecx 0/r32/eax
10306     89/<- *(edi+0xc) 0/r32/eax  # Block-var
10307     8b/-> *(ecx+4) 0/r32/eax
10308     89/<- *(edi+0x10) 0/r32/eax  # Block-var
10309 $parse-mu-named-block:end:
10310     # . reclaim locals
10311     81 0/subop/add %esp 8/imm32
10312     # . restore registers
10313     5f/pop-to-edi
10314     59/pop-to-ecx
10315     58/pop-to-eax
10316     # . epilogue
10317     89/<- %esp 5/r32/ebp
10318     5d/pop-to-ebp
10319     c3/return
10320 
10321 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)
10322     # . prologue
10323     55/push-ebp
10324     89/<- %ebp 4/r32/esp
10325     # . save registers
10326     50/push-eax
10327     51/push-ecx
10328     52/push-edx
10329     53/push-ebx
10330     57/push-edi
10331     # edi = out
10332     8b/-> *(ebp+0x10) 7/r32/edi
10333     # var word-slice/ecx: slice
10334     68/push 0/imm32/end
10335     68/push 0/imm32/start
10336     89/<- %ecx 4/r32/esp
10337     # var v/edx: (handle var)
10338     68/push 0/imm32
10339     68/push 0/imm32
10340     89/<- %edx 4/r32/esp
10341     # v = parse-var-with-type(next-mu-token(line))
10342     (next-mu-token *(ebp+8) %ecx)
10343     (parse-var-with-type %ecx *(ebp+8) %edx *(ebp+0x18) *(ebp+0x1c))
10344     # var v-addr/eax: (addr var)
10345     (lookup *edx *(edx+4))  # => eax
10346     # v->block-depth = *Curr-block-depth
10347     8b/-> *Curr-block-depth 3/r32/ebx
10348     89/<- *(eax+0x10) 3/r32/ebx  # Var-block-depth
10349     # either v has no register and there's no more to this line
10350     8b/-> *(eax+0x18) 0/r32/eax  # Var-register
10351     3d/compare-eax-and 0/imm32
10352     {
10353       75/jump-if-!= break/disp8
10354       # TODO: disallow vars of type 'byte' on the stack
10355       # ensure that there's nothing else on this line
10356       (next-mu-token *(ebp+8) %ecx)
10357       (slice-empty? %ecx)  # => eax
10358       3d/compare-eax-and 0/imm32/false
10359       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
10360       #
10361       (new-var-def Heap  *edx *(edx+4)  %edi)
10362       e9/jump $parse-mu-var-def:update-vars/disp32
10363     }
10364     # or v has a register and there's more to this line
10365     {
10366       0f 84/jump-if-= break/disp32
10367       # TODO: disallow vars of type 'byte' in registers 'esi' or 'edi'
10368       # TODO: vars of type 'byte' should only be initialized by clearing to 0
10369       # ensure that the next word is '<-'
10370       (next-mu-token *(ebp+8) %ecx)
10371       (slice-equal? %ecx "<-")  # => eax
10372       3d/compare-eax-and 0/imm32/false
10373       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
10374       #
10375       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
10376       (lookup *edi *(edi+4))  # => eax
10377       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
10378     }
10379 $parse-mu-var-def:update-vars:
10380     # push 'v' at end of function
10381     (push *(ebp+0xc) *edx)
10382     (push *(ebp+0xc) *(edx+4))
10383     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
10384 $parse-mu-var-def:end:
10385     # . reclaim locals
10386     81 0/subop/add %esp 0x10/imm32
10387     # . restore registers
10388     5f/pop-to-edi
10389     5b/pop-to-ebx
10390     5a/pop-to-edx
10391     59/pop-to-ecx
10392     58/pop-to-eax
10393     # . epilogue
10394     89/<- %esp 5/r32/ebp
10395     5d/pop-to-ebp
10396     c3/return
10397 
10398 $parse-mu-var-def:error1:
10399     (rewind-stream *(ebp+8))
10400     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
10401     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
10402     (flush *(ebp+0x18))
10403     (write-stream-data *(ebp+0x18) *(ebp+8))
10404     (write-buffered *(ebp+0x18) "'\n")
10405     (flush *(ebp+0x18))
10406     (stop *(ebp+0x1c) 1)
10407     # never gets here
10408 
10409 $parse-mu-var-def:error2:
10410     (rewind-stream *(ebp+8))
10411     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
10412     (write-buffered *(ebp+0x18) "fn ")
10413     8b/-> *(ebp+0x14) 0/r32/eax
10414     (lookup *eax *(eax+4))  # Function-name Function-name => eax
10415     (write-buffered *(ebp+0x18) %eax)
10416     (write-buffered *(ebp+0x18) ": var ")
10417     # var v-addr/eax: (addr var) = lookup(v)
10418     (lookup *edx *(edx+4))  # => eax
10419     (lookup *eax *(eax+4))  # Var-name Var-name => eax
10420     (write-buffered *(ebp+0x18) %eax)
10421     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
10422     (flush *(ebp+0x18))
10423     (stop *(ebp+0x1c) 1)
10424     # never gets here
10425 
10426 test-parse-mu-var-def:
10427     # 'var n: int'
10428     # . prologue
10429     55/push-ebp
10430     89/<- %ebp 4/r32/esp
10431     # setup
10432     8b/-> *Primitive-type-ids 0/r32/eax
10433     89/<- *Type-id 0/r32/eax  # stream-write
10434     (clear-stream _test-input-stream)
10435     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
10436     c7 0/subop/copy *Curr-block-depth 1/imm32
10437     # var out/esi: (handle stmt)
10438     68/push 0/imm32
10439     68/push 0/imm32
10440     89/<- %esi 4/r32/esp
10441     # var vars/ecx: (stack (addr var) 16)
10442     81 5/subop/subtract %esp 0xc0/imm32
10443     68/push 0xc0/imm32/size
10444     68/push 0/imm32/top
10445     89/<- %ecx 4/r32/esp
10446     (clear-stack %ecx)
10447     # convert
10448     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
10449     # var out-addr/esi: (addr stmt)
10450     (lookup *esi *(esi+4))  # => eax
10451     89/<- %esi 0/r32/eax
10452     #
10453     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
10454     # var v/ecx: (addr var) = lookup(out->var)
10455     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
10456     89/<- %ecx 0/r32/eax
10457     # v->name
10458     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
10459     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
10460     # v->register
10461     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
10462     # v->block-depth
10463     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
10464     # v->type == int
10465     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
10466     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
10467     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
10468     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
10469     # . epilogue
10470     89/<- %esp 5/r32/ebp
10471     5d/pop-to-ebp
10472     c3/return
10473 
10474 test-parse-mu-reg-var-def:
10475     # 'var n/eax: int <- copy 0'
10476     # . prologue
10477     55/push-ebp
10478     89/<- %ebp 4/r32/esp
10479     # setup
10480     8b/-> *Primitive-type-ids 0/r32/eax
10481     89/<- *Type-id 0/r32/eax  # stream-write
10482     (clear-stream _test-input-stream)
10483     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
10484     c7 0/subop/copy *Curr-block-depth 1/imm32
10485     # var out/esi: (handle stmt)
10486     68/push 0/imm32
10487     68/push 0/imm32
10488     89/<- %esi 4/r32/esp
10489     # var vars/ecx: (stack (addr var) 16)
10490     81 5/subop/subtract %esp 0xc0/imm32
10491     68/push 0xc0/imm32/size
10492     68/push 0/imm32/top
10493     89/<- %ecx 4/r32/esp
10494     (clear-stack %ecx)
10495     # convert
10496     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
10497     # var out-addr/esi: (addr stmt)
10498     (lookup *esi *(esi+4))  # => eax
10499     89/<- %esi 0/r32/eax
10500     #
10501     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
10502     # var v/ecx: (addr var) = lookup(out->outputs->value)
10503     # . eax: (addr stmt-var) = lookup(out->outputs)
10504     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
10505     # .
10506     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
10507     # . eax: (addr var) = lookup(eax->value)
10508     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
10509     # . ecx = eax
10510     89/<- %ecx 0/r32/eax
10511     # v->name
10512     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
10513     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
10514     # v->register
10515     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
10516     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
10517     # v->block-depth
10518     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
10519     # v->type == int
10520     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
10521     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
10522     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
10523     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
10524     # . epilogue
10525     89/<- %esp 5/r32/ebp
10526     5d/pop-to-ebp
10527     c3/return
10528 
10529 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)
10530     # Carefully push any outputs on the vars stack _after_ reading the inputs
10531     # that may conflict with them.
10532     #
10533     # The only situation in which outputs are pushed here (when it's not a
10534     # 'var' vardef stmt), and so can possibly conflict with inputs, is if the
10535     # output is a function output.
10536     #
10537     # pseudocode:
10538     #   var name: slice
10539     #   allocate(Heap, Stmt-size, out)
10540     #   var out-addr: (addr stmt) = lookup(*out)
10541     #   out-addr->tag = stmt
10542     #   if stmt-has-outputs?(line)
10543     #     while true
10544     #       name = next-mu-token(line)
10545     #       if (name == '<-') break
10546     #       assert(is-identifier?(name))
10547     #       var v: (handle var) = lookup-var-or-find-in-fn-outputs(name, vars, fn)
10548     #       out-addr->outputs = append(v, out-addr->outputs)
10549     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
10550     #   for output in stmt->outputs:
10551     #     maybe-define-var(output, vars)
10552     #
10553     # . prologue
10554     55/push-ebp
10555     89/<- %ebp 4/r32/esp
10556     # . save registers
10557     50/push-eax
10558     51/push-ecx
10559     52/push-edx
10560     53/push-ebx
10561     57/push-edi
10562     # var name/ecx: slice
10563     68/push 0/imm32/end
10564     68/push 0/imm32/start
10565     89/<- %ecx 4/r32/esp
10566     # var is-deref?/edx: boolean = false
10567     ba/copy-to-edx 0/imm32/false
10568     # var v: (handle var)
10569     68/push 0/imm32
10570     68/push 0/imm32
10571     89/<- %ebx 4/r32/esp
10572     #
10573     (allocate Heap *Stmt-size *(ebp+0x14))
10574     # var out-addr/edi: (addr stmt) = lookup(*out)
10575     8b/-> *(ebp+0x14) 7/r32/edi
10576     (lookup *edi *(edi+4))  # => eax
10577     89/<- %edi 0/r32/eax
10578     # out-addr->tag = 1/stmt
10579     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
10580     {
10581       (stmt-has-outputs? *(ebp+8))
10582       3d/compare-eax-and 0/imm32/false
10583       0f 84/jump-if-= break/disp32
10584       {
10585 $parse-mu-stmt:read-outputs:
10586         # name = next-mu-token(line)
10587         (next-mu-token *(ebp+8) %ecx)
10588         # if slice-empty?(word-slice) break
10589         (slice-empty? %ecx)  # => eax
10590         3d/compare-eax-and 0/imm32/false
10591         0f 85/jump-if-!= break/disp32
10592         # if (name == "<-") break
10593         (slice-equal? %ecx "<-")  # => eax
10594         3d/compare-eax-and 0/imm32/false
10595         0f 85/jump-if-!= break/disp32
10596         # is-deref? = false
10597         ba/copy-to-edx 0/imm32/false
10598         # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
10599         8b/-> *ecx 0/r32/eax  # Slice-start
10600         8a/copy-byte *eax 0/r32/AL
10601         81 4/subop/and %eax 0xff/imm32
10602         3d/compare-eax-and 0x2a/imm32/asterisk
10603         {
10604           75/jump-if-!= break/disp8
10605           ff 0/subop/increment *ecx
10606           ba/copy-to-edx 1/imm32/true
10607         }
10608         # assert(is-identifier?(name))
10609         (is-identifier? %ecx)  # => eax
10610         3d/compare-eax-and 0/imm32/false
10611         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
10612         #
10613         (lookup-var-or-find-in-fn-outputs %ecx *(ebp+0xc) *(ebp+0x10) %ebx *(ebp+0x18) *(ebp+0x1c))
10614         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
10615         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  %edx  %eax)  # Stmt1-outputs
10616         #
10617         e9/jump loop/disp32
10618       }
10619     }
10620     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
10621 $parse-mu-stmt:define-outputs:
10622     # var output/edi: (addr stmt-var) = lookup(out-addr->outputs)
10623     (lookup *(edi+0x14) *(edi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
10624     89/<- %edi 0/r32/eax
10625     {
10626 $parse-mu-stmt:define-outputs-loop:
10627       # if (output == null) break
10628       81 7/subop/compare %edi 0/imm32
10629       74/jump-if-= break/disp8
10630       #
10631       (maybe-define-var *edi *(edi+4)  *(ebp+0xc))  # if output is a deref, then it's already been defined,
10632                                                     # and must be in vars. This call will be a no-op, but safe.
10633       # output = output->next
10634       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
10635       89/<- %edi 0/r32/eax
10636       #
10637       eb/jump loop/disp8
10638     }
10639 $parse-mu-stmt:end:
10640     # . reclaim locals
10641     81 0/subop/add %esp 0x10/imm32
10642     # . restore registers
10643     5f/pop-to-edi
10644     5b/pop-to-ebx
10645     5a/pop-to-edx
10646     59/pop-to-ecx
10647     58/pop-to-eax
10648     # . epilogue
10649     89/<- %esp 5/r32/ebp
10650     5d/pop-to-ebp
10651     c3/return
10652 
10653 $parse-mu-stmt:abort:
10654     # error("invalid identifier '" name "'\n")
10655     (write-buffered *(ebp+0x18) "invalid identifier '")
10656     (write-slice-buffered *(ebp+0x18) %ecx)
10657     (write-buffered *(ebp+0x18) "'\n")
10658     (flush *(ebp+0x18))
10659     (stop *(ebp+0x1c) 1)
10660     # never gets here
10661 
10662 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)
10663     # pseudocode:
10664     #   stmt->name = slice-to-string(next-mu-token(line))
10665     #   while true
10666     #     name = next-mu-token(line)
10667     #     v = lookup-var-or-literal(name)
10668     #     stmt->inouts = append(v, stmt->inouts)
10669     #
10670     # . prologue
10671     55/push-ebp
10672     89/<- %ebp 4/r32/esp
10673     # . save registers
10674     50/push-eax
10675     51/push-ecx
10676     52/push-edx
10677     53/push-ebx
10678     56/push-esi
10679     57/push-edi
10680     # edi = stmt
10681     8b/-> *(ebp+8) 7/r32/edi
10682     # var name/ecx: slice
10683     68/push 0/imm32/end
10684     68/push 0/imm32/start
10685     89/<- %ecx 4/r32/esp
10686     # var is-deref?/edx: boolean = false
10687     ba/copy-to-edx 0/imm32/false
10688     # var v/esi: (handle var)
10689     68/push 0/imm32
10690     68/push 0/imm32
10691     89/<- %esi 4/r32/esp
10692 $add-operation-and-inputs-to-stmt:read-operation:
10693     (next-mu-token *(ebp+0xc) %ecx)
10694     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
10695     (slice-to-string Heap %ecx %eax)
10696     # var is-get?/ebx: boolean = (name == "get")
10697     (slice-equal? %ecx "get")  # => eax
10698     89/<- %ebx 0/r32/eax
10699     {
10700 $add-operation-and-inputs-to-stmt:read-inouts:
10701       # name = next-mu-token(line)
10702       (next-mu-token *(ebp+0xc) %ecx)
10703       # if slice-empty?(word-slice) break
10704       (slice-empty? %ecx)  # => eax
10705       3d/compare-eax-and 0/imm32/false
10706       0f 85/jump-if-!= break/disp32
10707       # if (name == "<-") abort
10708       (slice-equal? %ecx "<-")
10709       3d/compare-eax-and 0/imm32/false
10710       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
10711       # if (is-get? && second operand) lookup or create offset
10712       {
10713         81 7/subop/compare %ebx 0/imm32/false
10714         74/jump-if-= break/disp8
10715         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
10716         3d/compare-eax-and 0/imm32
10717         74/jump-if-= break/disp8
10718         (lookup-or-create-constant %eax %ecx %esi)
10719 #?         (lookup *esi *(esi+4))
10720 #?         (write-buffered Stderr "creating new output var ")
10721 #?         (write-int32-hex-buffered Stderr %eax)
10722 #?         (write-buffered Stderr " for field called ")
10723 #?         (write-slice-buffered Stderr %ecx)
10724 #?         (write-buffered Stderr "; var name ")
10725 #?         (lookup *eax *(eax+4))  # Var-name
10726 #?         (write-buffered Stderr %eax)
10727 #?         (write-buffered Stderr Newline)
10728 #?         (flush Stderr)
10729         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
10730       }
10731       # is-deref? = false
10732       ba/copy-to-edx 0/imm32/false
10733       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
10734       8b/-> *ecx 0/r32/eax  # Slice-start
10735       8a/copy-byte *eax 0/r32/AL
10736       81 4/subop/and %eax 0xff/imm32
10737       3d/compare-eax-and 0x2a/imm32/asterisk
10738       {
10739         75/jump-if-!= break/disp8
10740 $add-operation-and-inputs-to-stmt:inout-is-deref:
10741         ff 0/subop/increment *ecx
10742         ba/copy-to-edx 1/imm32/true
10743       }
10744       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
10745 $add-operation-and-inputs-to-stmt:save-var:
10746       8d/copy-address *(edi+0xc) 0/r32/eax
10747       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
10748       #
10749       e9/jump loop/disp32
10750     }
10751 $add-operation-and-inputs-to-stmt:end:
10752     # . reclaim locals
10753     81 0/subop/add %esp 0x10/imm32
10754     # . restore registers
10755     5f/pop-to-edi
10756     5e/pop-to-esi
10757     5b/pop-to-ebx
10758     5a/pop-to-edx
10759     59/pop-to-ecx
10760     58/pop-to-eax
10761     # . epilogue
10762     89/<- %esp 5/r32/ebp
10763     5d/pop-to-ebp
10764     c3/return
10765 
10766 $add-operation-and-inputs-to-stmt:abort:
10767     # error("fn ___: invalid identifier in '" line "'\n")
10768     (write-buffered *(ebp+0x18) "fn ")
10769     8b/-> *(ebp+0x14) 0/r32/eax
10770     (lookup *eax *(eax+4))  # Function-name Function-name => eax
10771     (write-buffered *(ebp+0x18) %eax)
10772     (rewind-stream *(ebp+0xc))
10773     (write-buffered *(ebp+0x18) ": invalid identifier in '")
10774     (write-stream-data *(ebp+0x18) *(ebp+0xc))
10775     (write-buffered *(ebp+0x18) "'\n")
10776     (flush *(ebp+0x18))
10777     (stop *(ebp+0x1c) 1)
10778     # never gets here
10779 
10780 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
10781     # . prologue
10782     55/push-ebp
10783     89/<- %ebp 4/r32/esp
10784     # . save registers
10785     51/push-ecx
10786     # var word-slice/ecx: slice
10787     68/push 0/imm32/end
10788     68/push 0/imm32/start
10789     89/<- %ecx 4/r32/esp
10790     # result = false
10791     b8/copy-to-eax 0/imm32/false
10792     (rewind-stream *(ebp+8))
10793     {
10794       (next-mu-token *(ebp+8) %ecx)
10795       # if slice-empty?(word-slice) break
10796       (slice-empty? %ecx)
10797       3d/compare-eax-and 0/imm32/false
10798       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
10799       0f 85/jump-if-!= break/disp32
10800       # if slice-starts-with?(word-slice, '#') break
10801       # . eax = *word-slice->start
10802       8b/-> *ecx 0/r32/eax
10803       8a/copy-byte *eax 0/r32/AL
10804       81 4/subop/and %eax 0xff/imm32
10805       # . if (eax == '#') break
10806       3d/compare-eax-and 0x23/imm32/hash
10807       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
10808       0f 84/jump-if-= break/disp32
10809       # if slice-equal?(word-slice, '<-') return true
10810       (slice-equal? %ecx "<-")
10811       3d/compare-eax-and 0/imm32/false
10812       74/jump-if-= loop/disp8
10813       b8/copy-to-eax 1/imm32/true
10814     }
10815 $stmt-has-outputs:end:
10816     (rewind-stream *(ebp+8))
10817     # . reclaim locals
10818     81 0/subop/add %esp 8/imm32
10819     # . restore registers
10820     59/pop-to-ecx
10821     # . epilogue
10822     89/<- %esp 5/r32/ebp
10823     5d/pop-to-ebp
10824     c3/return
10825 
10826 # if 'name' starts with a digit, create a new literal var for it
10827 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
10828 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)
10829     # . prologue
10830     55/push-ebp
10831     89/<- %ebp 4/r32/esp
10832     # . save registers
10833     50/push-eax
10834     51/push-ecx
10835     56/push-esi
10836     # esi = name
10837     8b/-> *(ebp+8) 6/r32/esi
10838     # if slice-empty?(name) abort
10839     (slice-empty? %esi)  # => eax
10840     3d/compare-eax-and 0/imm32/false
10841     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
10842     # var c/ecx: byte = *name->start
10843     8b/-> *esi 1/r32/ecx
10844     8a/copy-byte *ecx 1/r32/CL
10845     81 4/subop/and %ecx 0xff/imm32
10846     # if (is-decimal-digit?(c) || c == '-') return new var(name)
10847     {
10848       81 7/subop/compare %ecx 0x2d/imm32/dash
10849       74/jump-if-= $lookup-var-or-literal:literal/disp8
10850       (is-decimal-digit? %ecx)  # => eax
10851       3d/compare-eax-and 0/imm32/false
10852       74/jump-if-= break/disp8
10853 $lookup-var-or-literal:literal:
10854       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
10855       eb/jump $lookup-var-or-literal:end/disp8
10856     }
10857     # else if (c == '"') return new var(name)
10858     {
10859       81 7/subop/compare %ecx 0x22/imm32/dquote
10860       75/jump-if-!= break/disp8
10861 $lookup-var-or-literal:literal-string:
10862       (new-literal Heap %esi *(ebp+0x10))
10863       eb/jump $lookup-var-or-literal:end/disp8
10864     }
10865     # otherwise return lookup-var(name, vars)
10866     {
10867 $lookup-var-or-literal:var:
10868       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
10869     }
10870 $lookup-var-or-literal:end:
10871     # . restore registers
10872     5e/pop-to-esi
10873     59/pop-to-ecx
10874     58/pop-to-eax
10875     # . epilogue
10876     89/<- %esp 5/r32/ebp
10877     5d/pop-to-ebp
10878     c3/return
10879 
10880 $lookup-var-or-literal:abort:
10881     (write-buffered *(ebp+0x18) "fn ")
10882     8b/-> *(ebp+0x14) 0/r32/eax
10883     (lookup *eax *(eax+4))  # Function-name Function-name => eax
10884     (write-buffered *(ebp+0x18) %eax)
10885     (write-buffered *(ebp+0x18) ": empty variable!")
10886     (flush *(ebp+0x18))
10887     (stop *(ebp+0x1c) 1)
10888     # never gets here
10889 
10890 # return first 'name' from the top (back) of 'vars' and abort if not found
10891 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)
10892     # . prologue
10893     55/push-ebp
10894     89/<- %ebp 4/r32/esp
10895     # . save registers
10896     50/push-eax
10897     #
10898     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
10899     # if (*out == 0) abort
10900     8b/-> *(ebp+0x10) 0/r32/eax
10901     81 7/subop/compare *eax 0/imm32
10902     74/jump-if-= $lookup-var:abort/disp8
10903 $lookup-var:end:
10904     # . restore registers
10905     58/pop-to-eax
10906     # . epilogue
10907     89/<- %esp 5/r32/ebp
10908     5d/pop-to-ebp
10909     c3/return
10910 
10911 $lookup-var:abort:
10912     (write-buffered *(ebp+0x18) "fn ")
10913     8b/-> *(ebp+0x14) 0/r32/eax
10914     (lookup *eax *(eax+4))  # Function-name Function-name => eax
10915     (write-buffered *(ebp+0x18) %eax)
10916     (write-buffered *(ebp+0x18) ": unknown variable '")
10917     (write-slice-buffered *(ebp+0x18) *(ebp+8))
10918     (write-buffered *(ebp+0x18) "'\n")
10919     (flush *(ebp+0x18))
10920     (stop *(ebp+0x1c) 1)
10921     # never gets here
10922 
10923 # return first 'name' from the top (back) of 'vars', and 0/null if not found
10924 # ensure that 'name' if in a register is the topmost variable in that register
10925 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)
10926     # pseudocode:
10927     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
10928     #   var min = vars->data
10929     #   while curr >= min
10930     #     var v: (handle var) = *curr
10931     #     if v->name == name
10932     #       return
10933     #     curr -= 12
10934     #
10935     # . prologue
10936     55/push-ebp
10937     89/<- %ebp 4/r32/esp
10938     # . save registers
10939     50/push-eax
10940     51/push-ecx
10941     52/push-edx
10942     53/push-ebx
10943     56/push-esi
10944     57/push-edi
10945     # clear out
10946     (zero-out *(ebp+0x10) *Handle-size)
10947     # esi = vars
10948     8b/-> *(ebp+0xc) 6/r32/esi
10949     # ebx = vars->top
10950     8b/-> *esi 3/r32/ebx
10951     # if (vars->top > vars->size) abort
10952     3b/compare<- *(esi+4) 0/r32/eax
10953     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
10954     # var min/edx: (addr handle var) = vars->data
10955     8d/copy-address *(esi+8) 2/r32/edx
10956     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
10957     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
10958     # var var-in-reg/edi: 16 addrs
10959     68/push 0/imm32
10960     68/push 0/imm32
10961     68/push 0/imm32
10962     68/push 0/imm32
10963     68/push 0/imm32
10964     68/push 0/imm32
10965     68/push 0/imm32
10966     68/push 0/imm32
10967     68/push 0/imm32
10968     68/push 0/imm32
10969     68/push 0/imm32
10970     68/push 0/imm32
10971     68/push 0/imm32
10972     68/push 0/imm32
10973     68/push 0/imm32
10974     68/push 0/imm32
10975     89/<- %edi 4/r32/esp
10976     {
10977 $lookup-var-helper:loop:
10978       # if (curr < min) return
10979       39/compare %ebx 2/r32/edx
10980       0f 82/jump-if-addr< break/disp32
10981       # var v/ecx: (addr var) = lookup(*curr)
10982       (lookup *ebx *(ebx+4))  # => eax
10983       89/<- %ecx 0/r32/eax
10984       # var vn/eax: (addr array byte) = lookup(v->name)
10985       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
10986       # if (vn == name) return curr
10987       (slice-equal? *(ebp+8) %eax)  # => eax
10988       3d/compare-eax-and 0/imm32/false
10989       {
10990         74/jump-if-= break/disp8
10991 $lookup-var-helper:found:
10992         # var vr/eax: (addr array byte) = lookup(v->register)
10993         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
10994         3d/compare-eax-and 0/imm32
10995         {
10996           74/jump-if-= break/disp8
10997 $lookup-var-helper:found-register:
10998           # var reg/eax: int = get(Registers, vr)
10999           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
11000           8b/-> *eax 0/r32/eax
11001           # if (var-in-reg[reg]) error
11002           8b/-> *(edi+eax<<2) 0/r32/eax
11003           3d/compare-eax-and 0/imm32
11004           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
11005         }
11006 $lookup-var-helper:return:
11007         # esi = out
11008         8b/-> *(ebp+0x10) 6/r32/esi
11009         # *out = *curr
11010         8b/-> *ebx 0/r32/eax
11011         89/<- *esi 0/r32/eax
11012         8b/-> *(ebx+4) 0/r32/eax
11013         89/<- *(esi+4) 0/r32/eax
11014         # return
11015         eb/jump $lookup-var-helper:end/disp8
11016       }
11017       # 'name' not yet found; update var-in-reg if v in register
11018       # . var vr/eax: (addr array byte) = lookup(v->register)
11019       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
11020       # . if (vr == 0) continue
11021       3d/compare-eax-and 0/imm32
11022       74/jump-if-= $lookup-var-helper:continue/disp8
11023       # . var reg/eax: int = get(Registers, vr)
11024       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
11025       8b/-> *eax 0/r32/eax
11026       # . var-in-reg[reg] = v
11027       89/<- *(edi+eax<<2) 1/r32/ecx
11028 $lookup-var-helper:continue:
11029       # curr -= 12
11030       81 5/subop/subtract %ebx 0xc/imm32
11031       e9/jump loop/disp32
11032     }
11033 $lookup-var-helper:end:
11034     # . reclaim locals
11035     81 0/subop/add %esp 0x40/imm32
11036     # . restore registers
11037     5f/pop-to-edi
11038     5e/pop-to-esi
11039     5b/pop-to-ebx
11040     5a/pop-to-edx
11041     59/pop-to-ecx
11042     58/pop-to-eax
11043     # . epilogue
11044     89/<- %esp 5/r32/ebp
11045     5d/pop-to-ebp
11046     c3/return
11047 
11048 $lookup-var-helper:error1:
11049     (write-buffered *(ebp+0x18) "fn ")
11050     8b/-> *(ebp+0x14) 0/r32/eax
11051     (lookup *eax *(eax+4))  # Function-name Function-name => eax
11052     (write-buffered *(ebp+0x18) %eax)
11053     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
11054     (write-slice-buffered *(ebp+0x18) *(ebp+8))
11055     (write-buffered *(ebp+0x18) "'\n")
11056     (flush *(ebp+0x18))
11057     (stop *(ebp+0x1c) 1)
11058     # never gets here
11059 
11060 $lookup-var-helper:error2:
11061     # eax contains the conflicting var at this point
11062     (write-buffered *(ebp+0x18) "fn ")
11063     50/push-eax
11064     8b/-> *(ebp+0x14) 0/r32/eax
11065     (lookup *eax *(eax+4))  # Function-name Function-name => eax
11066     (write-buffered *(ebp+0x18) %eax)
11067     58/pop-eax
11068     (write-buffered *(ebp+0x18) ": register ")
11069     50/push-eax
11070     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
11071     (write-buffered *(ebp+0x18) %eax)
11072     58/pop-to-eax
11073     (write-buffered *(ebp+0x18) " reads var '")
11074     (write-slice-buffered *(ebp+0x18) *(ebp+8))
11075     (write-buffered *(ebp+0x18) "' after writing var '")
11076     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11077     (write-buffered *(ebp+0x18) %eax)
11078     (write-buffered *(ebp+0x18) "'\n")
11079     (flush *(ebp+0x18))
11080     (stop *(ebp+0x1c) 1)
11081     # never gets here
11082 
11083 dump-vars:  # vars: (addr stack live-var)
11084     # pseudocode:
11085     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
11086     #   var min = vars->data
11087     #   while curr >= min
11088     #     var v: (handle var) = *curr
11089     #     print v
11090     #     curr -= 12
11091     #
11092     # . prologue
11093     55/push-ebp
11094     89/<- %ebp 4/r32/esp
11095     # . save registers
11096     52/push-edx
11097     53/push-ebx
11098     56/push-esi
11099     # esi = vars
11100     8b/-> *(ebp+8) 6/r32/esi
11101     # ebx = vars->top
11102     8b/-> *esi 3/r32/ebx
11103     # var min/edx: (addr handle var) = vars->data
11104     8d/copy-address *(esi+8) 2/r32/edx
11105     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
11106     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
11107     {
11108 $dump-vars:loop:
11109       # if (curr < min) return
11110       39/compare %ebx 2/r32/edx
11111       0f 82/jump-if-addr< break/disp32
11112       #
11113       (write-buffered Stderr "  var@")
11114       (dump-var 2 %ebx)
11115       # curr -= 12
11116       81 5/subop/subtract %ebx 0xc/imm32
11117       e9/jump loop/disp32
11118     }
11119 $dump-vars:end:
11120     # . restore registers
11121     5e/pop-to-esi
11122     5b/pop-to-ebx
11123     5a/pop-to-edx
11124     # . epilogue
11125     89/<- %esp 5/r32/ebp
11126     5d/pop-to-ebp
11127     c3/return
11128 
11129 == data
11130 # Like Registers, but no esp or ebp
11131 Mu-registers:  # (addr stream {(handle array byte), int})
11132   # a table is a stream
11133   0xa8/imm32/write
11134   0/imm32/read
11135   0xa8/imm32/length
11136   # data
11137   # general-purpose registers
11138   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
11139   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
11140   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
11141   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
11142   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
11143   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
11144   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
11145   # floating-point registers
11146   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
11147   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
11148   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
11149   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
11150   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
11151   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
11152   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
11153   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
11154 
11155 # Like Mu-registers, but with unique codes for integer and floating-point
11156 # registers.
11157 # Don't use this for code-generation, only for checking.
11158 Mu-registers-unique:  # (addr stream {(handle array byte), int})
11159   # a table is a stream
11160   0xa8/imm32/write
11161   0/imm32/read
11162   0xa8/imm32/length
11163   # data
11164   # general-purpose registers
11165   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
11166   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
11167   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
11168   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
11169   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
11170   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
11171   # floating-point registers
11172   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
11173   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
11174   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
11175   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
11176   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
11177   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
11178   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
11179   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
11180 
11181 $Mu-register-eax:
11182   0x11/imm32/alloc-id
11183   3/imm32/size
11184   0x65/e 0x61/a 0x78/x
11185 
11186 $Mu-register-ecx:
11187   0x11/imm32/alloc-id
11188   3/imm32/size
11189   0x65/e 0x63/c 0x78/x
11190 
11191 $Mu-register-edx:
11192   0x11/imm32/alloc-id
11193   3/imm32/size
11194   0x65/e 0x64/d 0x78/x
11195 
11196 $Mu-register-ebx:
11197   0x11/imm32/alloc-id
11198   3/imm32/size
11199   0x65/e 0x62/b 0x78/x
11200 
11201 $Mu-register-esi:
11202   0x11/imm32/alloc-id
11203   3/imm32/size
11204   0x65/e 0x73/s 0x69/i
11205 
11206 $Mu-register-edi:
11207   0x11/imm32/alloc-id
11208   3/imm32/size
11209   0x65/e 0x64/d 0x69/i
11210 
11211 $Mu-register-xmm0:
11212   0x11/imm32/alloc-id:fake:payload
11213   # "xmm0"
11214   0x4/imm32/size
11215   0x78/x 0x6d/m 0x6d/m 0x30/0
11216 
11217 $Mu-register-xmm1:
11218   0x11/imm32/alloc-id:fake:payload
11219   # "xmm1"
11220   0x4/imm32/size
11221   0x78/x 0x6d/m 0x6d/m 0x31/1
11222 
11223 $Mu-register-xmm2:
11224   0x11/imm32/alloc-id:fake:payload
11225   # "xmm2"
11226   0x4/imm32/size
11227   0x78/x 0x6d/m 0x6d/m 0x32/2
11228 
11229 $Mu-register-xmm3:
11230   0x11/imm32/alloc-id:fake:payload
11231   # "xmm3"
11232   0x4/imm32/size
11233   0x78/x 0x6d/m 0x6d/m 0x33/3
11234 
11235 $Mu-register-xmm4:
11236   0x11/imm32/alloc-id:fake:payload
11237   # "xmm4"
11238   0x4/imm32/size
11239   0x78/x 0x6d/m 0x6d/m 0x34/4
11240 
11241 $Mu-register-xmm5:
11242   0x11/imm32/alloc-id:fake:payload
11243   # "xmm5"
11244   0x4/imm32/size
11245   0x78/x 0x6d/m 0x6d/m 0x35/5
11246 
11247 $Mu-register-xmm6:
11248   0x11/imm32/alloc-id:fake:payload
11249   # "xmm6"
11250   0x4/imm32/size
11251   0x78/x 0x6d/m 0x6d/m 0x36/6
11252 
11253 $Mu-register-xmm7:
11254   0x11/imm32/alloc-id:fake:payload
11255   # "xmm7"
11256   0x4/imm32/size
11257   0x78/x 0x6d/m 0x6d/m 0x37/7
11258 
11259 == code
11260 
11261 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found
11262 lookup-var-or-find-in-fn-outputs:  # name: (addr slice), vars: (addr stack live-var), fn: (addr function), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
11263     # . prologue
11264     55/push-ebp
11265     89/<- %ebp 4/r32/esp
11266     # . save registers
11267     50/push-eax
11268     #
11269     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))  # arg order slightly different; 'fn' is deemphasized
11270     {
11271       # if (out != 0) return
11272       8b/-> *(ebp+0x14) 0/r32/eax
11273       81 7/subop/compare *eax 0/imm32
11274       75/jump-if-!= break/disp8
11275       # if name is one of fn's outputs, return it
11276       (find-in-function-outputs *(ebp+0x10) *(ebp+8) *(ebp+0x14))
11277       8b/-> *(ebp+0x14) 0/r32/eax
11278       81 7/subop/compare *eax 0/imm32
11279       # otherwise abort
11280       0f 84/jump-if-= $lookup-or-define-var:abort/disp32
11281     }
11282 $lookup-or-define-var:end:
11283     # . restore registers
11284     58/pop-to-eax
11285     # . epilogue
11286     89/<- %esp 5/r32/ebp
11287     5d/pop-to-ebp
11288     c3/return
11289 
11290 $lookup-or-define-var:abort:
11291     (write-buffered *(ebp+0x18) "unknown variable '")
11292     (write-slice-buffered *(ebp+0x18) *(ebp+8))
11293     (write-buffered *(ebp+0x18) "'\n")
11294     (flush *(ebp+0x18))
11295     (stop *(ebp+0x1c) 1)
11296     # never gets here
11297 
11298 find-in-function-outputs:  # fn: (addr function), name: (addr slice), out: (addr handle var)
11299     # . prologue
11300     55/push-ebp
11301     89/<- %ebp 4/r32/esp
11302     # . save registers
11303     50/push-eax
11304     51/push-ecx
11305     # var curr/ecx: (addr list var) = lookup(fn->outputs)
11306     8b/-> *(ebp+8) 1/r32/ecx
11307     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
11308     89/<- %ecx 0/r32/eax
11309     # while curr != null
11310     {
11311       81 7/subop/compare %ecx 0/imm32
11312       74/jump-if-= break/disp8
11313       # var v/eax: (addr var) = lookup(curr->value)
11314       (lookup *ecx *(ecx+4))  # List-value List-value => eax
11315       # var s/eax: (addr array byte) = lookup(v->name)
11316       (lookup *eax *(eax+4))  # Var-name Var-name => eax
11317       # if (s == name) return curr->value
11318       (slice-equal? *(ebp+0xc) %eax)  # => eax
11319       3d/compare-eax-and 0/imm32/false
11320       {
11321         74/jump-if-= break/disp8
11322         # var edi = out
11323         57/push-edi
11324         8b/-> *(ebp+0x10) 7/r32/edi
11325         # *out = curr->value
11326         8b/-> *ecx 0/r32/eax
11327         89/<- *edi 0/r32/eax
11328         8b/-> *(ecx+4) 0/r32/eax
11329         89/<- *(edi+4) 0/r32/eax
11330         #
11331         5f/pop-to-edi
11332         eb/jump $find-in-function-outputs:end/disp8
11333       }
11334       # curr = curr->next
11335       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
11336       89/<- %ecx 0/r32/eax
11337       #
11338       eb/jump loop/disp8
11339     }
11340     b8/copy-to-eax 0/imm32
11341 $find-in-function-outputs:end:
11342     # . restore registers
11343     59/pop-to-ecx
11344     58/pop-to-eax
11345     # . epilogue
11346     89/<- %esp 5/r32/ebp
11347     5d/pop-to-ebp
11348     c3/return
11349 
11350 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
11351 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
11352     # . prologue
11353     55/push-ebp
11354     89/<- %ebp 4/r32/esp
11355     # . save registers
11356     50/push-eax
11357     # var out-addr/eax: (addr var)
11358     (lookup *(ebp+8) *(ebp+0xc))  # => eax
11359     #
11360     (binding-exists? %eax *(ebp+0x10))  # => eax
11361     3d/compare-eax-and 0/imm32/false
11362     75/jump-if-!= $maybe-define-var:end/disp8
11363     # otherwise update vars
11364     (push *(ebp+0x10) *(ebp+8))
11365     (push *(ebp+0x10) *(ebp+0xc))
11366     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
11367 $maybe-define-var:end:
11368     # . restore registers
11369     58/pop-to-eax
11370     # . epilogue
11371     89/<- %esp 5/r32/ebp
11372     5d/pop-to-ebp
11373     c3/return
11374 
11375 # simpler version of lookup-var-helper
11376 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
11377     # pseudocode:
11378     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
11379     #   var min = vars->data
11380     #   while curr >= min
11381     #     var v: (handle var) = *curr
11382     #     if v->name == target->name
11383     #       return true
11384     #     curr -= 12
11385     #   return false
11386     #
11387     # . prologue
11388     55/push-ebp
11389     89/<- %ebp 4/r32/esp
11390     # . save registers
11391     51/push-ecx
11392     52/push-edx
11393     56/push-esi
11394     # var target-name/ecx: (addr array byte) = lookup(target->name)
11395     8b/-> *(ebp+8) 0/r32/eax
11396     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11397     89/<- %ecx 0/r32/eax
11398     # esi = vars
11399     8b/-> *(ebp+0xc) 6/r32/esi
11400     # eax = vars->top
11401     8b/-> *esi 0/r32/eax
11402     # var min/edx: (addr handle var) = vars->data
11403     8d/copy-address *(esi+8) 2/r32/edx
11404     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
11405     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
11406     {
11407 $binding-exists?:loop:
11408       # if (curr < min) return
11409       39/compare %esi 2/r32/edx
11410       0f 82/jump-if-addr< break/disp32
11411       # var v/eax: (addr var) = lookup(*curr)
11412       (lookup *esi *(esi+4))  # => eax
11413       # var vn/eax: (addr array byte) = lookup(v->name)
11414       (lookup *eax *(eax+4))  # Var-name Var-name => eax
11415       # if (vn == target-name) return true
11416       (string-equal? %ecx %eax)  # => eax
11417       3d/compare-eax-and 0/imm32/false
11418       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
11419       # curr -= 12
11420       81 5/subop/subtract %esi 0xc/imm32
11421       e9/jump loop/disp32
11422     }
11423     b8/copy-to-eax 0/imm32/false
11424 $binding-exists?:end:
11425     # . restore registers
11426     5e/pop-to-esi
11427     5a/pop-to-edx
11428     59/pop-to-ecx
11429     # . epilogue
11430     89/<- %esp 5/r32/ebp
11431     5d/pop-to-ebp
11432     c3/return
11433 
11434 test-parse-mu-stmt:
11435     # . prologue
11436     55/push-ebp
11437     89/<- %ebp 4/r32/esp
11438     # setup
11439     8b/-> *Primitive-type-ids 0/r32/eax
11440     89/<- *Type-id 0/r32/eax  # stream-write
11441     (clear-stream _test-input-stream)
11442     (write _test-input-stream "increment n\n")
11443     # var vars/ecx: (stack (addr var) 16)
11444     81 5/subop/subtract %esp 0xc0/imm32
11445     68/push 0xc0/imm32/size
11446     68/push 0/imm32/top
11447     89/<- %ecx 4/r32/esp
11448     (clear-stack %ecx)
11449     # var v/edx: (handle var)
11450     68/push 0/imm32
11451     68/push 0/imm32
11452     89/<- %edx 4/r32/esp
11453     # var s/eax: (handle array byte)
11454     68/push 0/imm32
11455     68/push 0/imm32
11456     89/<- %eax 4/r32/esp
11457     # v = new var("n")
11458     (copy-array Heap "n" %eax)
11459     (new-var Heap *eax *(eax+4) %edx)
11460     #
11461     (push %ecx *edx)
11462     (push %ecx *(edx+4))
11463     (push %ecx 0)
11464     # var out/eax: (handle stmt)
11465     68/push 0/imm32
11466     68/push 0/imm32
11467     89/<- %eax 4/r32/esp
11468     # convert
11469     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
11470     # var out-addr/edx: (addr stmt) = lookup(*out)
11471     (lookup *eax *(eax+4))  # => eax
11472     89/<- %edx 0/r32/eax
11473     # out->tag
11474     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
11475     # out->operation
11476     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
11477     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
11478     # out->inouts->value->name
11479     # . eax = out->inouts
11480     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
11481     # . eax = out->inouts->value
11482     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
11483     # . eax = out->inouts->value->name
11484     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11485     # .
11486     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
11487     # . epilogue
11488     89/<- %esp 5/r32/ebp
11489     5d/pop-to-ebp
11490     c3/return
11491 
11492 test-parse-mu-stmt-with-comma:
11493     # . prologue
11494     55/push-ebp
11495     89/<- %ebp 4/r32/esp
11496     # setup
11497     8b/-> *Primitive-type-ids 0/r32/eax
11498     89/<- *Type-id 0/r32/eax  # stream-write
11499     (clear-stream _test-input-stream)
11500     (write _test-input-stream "copy-to n, 3\n")
11501     # var vars/ecx: (stack (addr var) 16)
11502     81 5/subop/subtract %esp 0xc0/imm32
11503     68/push 0xc0/imm32/size
11504     68/push 0/imm32/top
11505     89/<- %ecx 4/r32/esp
11506     (clear-stack %ecx)
11507     # var v/edx: (handle var)
11508     68/push 0/imm32
11509     68/push 0/imm32
11510     89/<- %edx 4/r32/esp
11511     # var s/eax: (handle array byte)
11512     68/push 0/imm32
11513     68/push 0/imm32
11514     89/<- %eax 4/r32/esp
11515     # v = new var("n")
11516     (copy-array Heap "n" %eax)
11517     (new-var Heap *eax *(eax+4) %edx)
11518     #
11519     (push %ecx *edx)
11520     (push %ecx *(edx+4))
11521     (push %ecx 0)
11522     # var out/eax: (handle stmt)
11523     68/push 0/imm32
11524     68/push 0/imm32
11525     89/<- %eax 4/r32/esp
11526     # convert
11527     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
11528     # var out-addr/edx: (addr stmt) = lookup(*out)
11529     (lookup *eax *(eax+4))  # => eax
11530     89/<- %edx 0/r32/eax
11531     # out->tag
11532     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
11533     # out->operation
11534     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
11535     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
11536     # out->inouts->value->name
11537     # . eax = out->inouts
11538     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
11539     # . eax = out->inouts->value
11540     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
11541     # . eax = out->inouts->value->name
11542     (lookup *eax *(eax+4))  # Var-name Var-name => eax
11543     # .
11544     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
11545     # . epilogue
11546     89/<- %esp 5/r32/ebp
11547     5d/pop-to-ebp
11548     c3/return
11549 
11550 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
11551     # . prologue
11552     55/push-ebp
11553     89/<- %ebp 4/r32/esp
11554     # . save registers
11555     50/push-eax
11556     51/push-ecx
11557     # ecx = out
11558     8b/-> *(ebp+0x14) 1/r32/ecx
11559     #
11560     (allocate *(ebp+8) *Var-size %ecx)
11561     # var out-addr/eax: (addr var)
11562     (lookup *ecx *(ecx+4))  # => eax
11563     # out-addr->name = name
11564     8b/-> *(ebp+0xc) 1/r32/ecx
11565     89/<- *eax 1/r32/ecx  # Var-name
11566     8b/-> *(ebp+0x10) 1/r32/ecx
11567     89/<- *(eax+4) 1/r32/ecx  # Var-name
11568 #?     (write-buffered Stderr "var ")
11569 #?     (lookup *(ebp+0xc) *(ebp+0x10))
11570 #?     (write-buffered Stderr %eax)
11571 #?     (write-buffered Stderr " at ")
11572 #?     8b/-> *(ebp+0x14) 1/r32/ecx
11573 #?     (lookup *ecx *(ecx+4))  # => eax
11574 #?     (write-int32-hex-buffered Stderr %eax)
11575 #?     (write-buffered Stderr Newline)
11576 #?     (flush Stderr)
11577 $new-var:end:
11578     # . restore registers
11579     59/pop-to-ecx
11580     58/pop-to-eax
11581     # . epilogue
11582     89/<- %esp 5/r32/ebp
11583     5d/pop-to-ebp
11584     c3/return
11585 
11586 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)
11587     # . prologue
11588     55/push-ebp
11589     89/<- %ebp 4/r32/esp
11590     # . save registers
11591     50/push-eax
11592     51/push-ecx
11593     # if (!is-hex-int?(name)) abort
11594     (is-hex-int? *(ebp+0xc))  # => eax
11595     3d/compare-eax-and 0/imm32/false
11596     0f 84/jump-if-= $new-literal-integer:abort/disp32
11597     # a little more error-checking
11598     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
11599     # out = new var(s)
11600     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
11601     # var out-addr/ecx: (addr var) = lookup(*out)
11602     8b/-> *(ebp+0x10) 0/r32/eax
11603     (lookup *eax *(eax+4))  # => eax
11604     89/<- %ecx 0/r32/eax
11605     # out-addr->block-depth = *Curr-block-depth
11606     8b/-> *Curr-block-depth 0/r32/eax
11607     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
11608     # out-addr->type = new tree()
11609     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
11610     (allocate *(ebp+8) *Type-tree-size %eax)
11611     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
11612     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
11613     # nothing else to do; default type is 'literal'
11614 $new-literal-integer:end:
11615     # . reclaim locals
11616     81 0/subop/add %esp 8/imm32
11617     # . restore registers
11618     59/pop-to-ecx
11619     58/pop-to-eax
11620     # . epilogue
11621     89/<- %esp 5/r32/ebp
11622     5d/pop-to-ebp
11623     c3/return
11624 
11625 $new-literal-integer:abort:
11626     (write-buffered *(ebp+0x18) "fn ")
11627     8b/-> *(ebp+0x14) 0/r32/eax
11628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
11629     (write-buffered *(ebp+0x18) %eax)
11630     (write-buffered *(ebp+0x18) ": variable '")
11631     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
11632     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
11633     (flush *(ebp+0x18))
11634     (stop *(ebp+0x1c) 1)
11635     # never gets here
11636 
11637 # precondition: name is a valid hex integer; require a '0x' prefix
11638 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
11639     # . prologue
11640     55/push-ebp
11641     89/<- %ebp 4/r32/esp
11642     # . save registers
11643     50/push-eax
11644     51/push-ecx
11645     52/push-edx
11646     # ecx = name
11647     8b/-> *(ebp+8) 1/r32/ecx
11648     # var start/edx: (addr byte) = name->start
11649     8b/-> *ecx 2/r32/edx
11650     # if (*start == '-') ++start
11651     b8/copy-to-eax 0/imm32
11652     8a/copy-byte *edx 0/r32/AL
11653     3d/compare-eax-and 0x2d/imm32/dash
11654     {
11655       75/jump-if-!= break/disp8
11656       42/increment-edx
11657     }
11658     # var end/ecx: (addr byte) = name->end
11659     8b/-> *(ecx+4) 1/r32/ecx
11660     # var len/eax: int = name->end - name->start
11661     89/<- %eax 1/r32/ecx
11662     29/subtract-from %eax 2/r32/edx
11663     # if (len <= 1) return
11664     3d/compare-eax-with 1/imm32
11665     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
11666 $check-mu-hex-int:length->-1:
11667     # if slice-starts-with?({start, end}, "0x") return
11668     # . var tmp = {start, end}
11669     51/push-ecx
11670     52/push-edx
11671     89/<- %eax 4/r32/esp
11672     # .
11673     (slice-starts-with? %eax "0x")  # => eax
11674     # . reclaim tmp
11675     81 0/subop/add %esp 8/imm32
11676     # .
11677     3d/compare-eax-with 0/imm32/false
11678     75/jump-if-!= $check-mu-hex-int:end/disp8
11679 $check-mu-hex-int:abort:
11680     # otherwise abort
11681     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; either start '")
11682     (write-slice-buffered *(ebp+0xc) *(ebp+8))
11683     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, or convert it to decimal.\n")
11684     (flush *(ebp+0xc))
11685     (stop *(ebp+0x10) 1)
11686 $check-mu-hex-int:end:
11687     # . restore registers
11688     5a/pop-to-edx
11689     59/pop-to-ecx
11690     58/pop-to-eax
11691     # . epilogue
11692     89/<- %esp 5/r32/ebp
11693     5d/pop-to-ebp
11694     c3/return
11695 
11696 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
11697     # . prologue
11698     55/push-ebp
11699     89/<- %ebp 4/r32/esp
11700     # . save registers
11701     50/push-eax
11702     51/push-ecx
11703     # var s/ecx: (handle array byte)
11704     68/push 0/imm32
11705     68/push 0/imm32
11706     89/<- %ecx 4/r32/esp
11707     # s = slice-to-string(name)
11708     (slice-to-string Heap *(ebp+0xc) %ecx)
11709     # allocate to out
11710     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
11711     # var out-addr/ecx: (addr var) = lookup(*out)
11712     8b/-> *(ebp+0x10) 1/r32/ecx
11713     (lookup *ecx *(ecx+4))  # => eax
11714     89/<- %ecx 0/r32/eax
11715     # out-addr->block-depth = *Curr-block-depth
11716     8b/-> *Curr-block-depth 0/r32/eax
11717     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
11718     # out-addr->type/eax = new type
11719     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
11720     (allocate *(ebp+8) *Type-tree-size %eax)
11721     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
11722     # nothing else to do; default type is 'literal'
11723     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
11724 $new-literal:end:
11725     # . reclaim locals
11726     81 0/subop/add %esp 8/imm32
11727     # . restore registers
11728     59/pop-to-ecx
11729     58/pop-to-eax
11730     # . epilogue
11731     89/<- %esp 5/r32/ebp
11732     5d/pop-to-ebp
11733     c3/return
11734 
11735 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
11736     # . prologue
11737     55/push-ebp
11738     89/<- %ebp 4/r32/esp
11739     # . save registers
11740     51/push-ecx
11741     # var tmp/ecx: (handle array byte)
11742     68/push 0/imm32
11743     68/push 0/imm32
11744     89/<- %ecx 4/r32/esp
11745     # tmp = slice-to-string(name)
11746     (slice-to-string Heap *(ebp+0xc) %ecx)
11747     # out = new-var(tmp)
11748     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
11749 $new-var-from-slice:end:
11750     # . reclaim locals
11751     81 0/subop/add %esp 8/imm32
11752     # . restore registers
11753     59/pop-to-ecx
11754     # . epilogue
11755     89/<- %esp 5/r32/ebp
11756     5d/pop-to-ebp
11757     c3/return
11758 
11759 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
11760     # . prologue
11761     55/push-ebp
11762     89/<- %ebp 4/r32/esp
11763     # . save registers
11764     50/push-eax
11765     51/push-ecx
11766     #
11767     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
11768     # var out-addr/eax: (addr stmt) = lookup(*out)
11769     8b/-> *(ebp+0x14) 0/r32/eax
11770     (lookup *eax *(eax+4))  # => eax
11771     # out-addr->tag = stmt
11772     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
11773     # result->var = var
11774     8b/-> *(ebp+0xc) 1/r32/ecx
11775     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
11776     8b/-> *(ebp+0x10) 1/r32/ecx
11777     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
11778 $new-var-def:end:
11779     # . restore registers
11780     59/pop-to-ecx
11781     58/pop-to-eax
11782     # . epilogue
11783     89/<- %esp 5/r32/ebp
11784     5d/pop-to-ebp
11785     c3/return
11786 
11787 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
11788     # . prologue
11789     55/push-ebp
11790     89/<- %ebp 4/r32/esp
11791     # . save registers
11792     50/push-eax
11793     # eax = out
11794     8b/-> *(ebp+0x14) 0/r32/eax
11795     #
11796     (allocate *(ebp+8) *Stmt-size %eax)
11797     # var out-addr/eax: (addr stmt) = lookup(*out)
11798     (lookup *eax *(eax+4))  # => eax
11799     # set tag
11800     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
11801     # set output
11802     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
11803     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
11804 $new-reg-var-def:end:
11805     # . restore registers
11806     58/pop-to-eax
11807     # . epilogue
11808     89/<- %esp 5/r32/ebp
11809     5d/pop-to-ebp
11810     c3/return
11811 
11812 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
11813     # . prologue
11814     55/push-ebp
11815     89/<- %ebp 4/r32/esp
11816     # . save registers
11817     50/push-eax
11818     51/push-ecx
11819     57/push-edi
11820     # edi = out
11821     8b/-> *(ebp+0x1c) 7/r32/edi
11822     # *out = new list
11823     (allocate *(ebp+8) *List-size %edi)
11824     # var out-addr/edi: (addr list _type) = lookup(*out)
11825     (lookup *edi *(edi+4))  # => eax
11826     89/<- %edi 0/r32/eax
11827     # out-addr->value = value
11828     8b/-> *(ebp+0xc) 0/r32/eax
11829     89/<- *edi 0/r32/eax  # List-value
11830     8b/-> *(ebp+0x10) 0/r32/eax
11831     89/<- *(edi+4) 0/r32/eax  # List-value
11832     # if (list == null) return
11833     81 7/subop/compare *(ebp+0x14) 0/imm32
11834     74/jump-if-= $append-list:end/disp8
11835     # otherwise append
11836 $append-list:non-empty-list:
11837     # var curr/eax: (addr list _type) = lookup(list)
11838     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
11839     # while (curr->next != null) curr = curr->next
11840     {
11841       81 7/subop/compare *(eax+8) 0/imm32  # List-next
11842       74/jump-if-= break/disp8
11843       # curr = lookup(curr->next)
11844       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
11845       #
11846       eb/jump loop/disp8
11847     }
11848     # edi = out
11849     8b/-> *(ebp+0x1c) 7/r32/edi
11850     # curr->next = out
11851     8b/-> *edi 1/r32/ecx
11852     89/<- *(eax+8) 1/r32/ecx  # List-next
11853     8b/-> *(edi+4) 1/r32/ecx
11854     89/<- *(eax+0xc) 1/r32/ecx  # List-next
11855     # out = list
11856     8b/-> *(ebp+0x14) 1/r32/ecx
11857     89/<- *edi 1/r32/ecx
11858     8b/-> *(ebp+0x18) 1/r32/ecx
11859     89/<- *(edi+4) 1/r32/ecx
11860 $append-list:end:
11861     # . restore registers
11862     5f/pop-to-edi
11863     59/pop-to-ecx
11864     58/pop-to-eax
11865     # . epilogue
11866     89/<- %esp 5/r32/ebp
11867     5d/pop-to-ebp
11868     c3/return
11869 
11870 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
11871     # . prologue
11872     55/push-ebp
11873     89/<- %ebp 4/r32/esp
11874     # . save registers
11875     50/push-eax
11876     51/push-ecx
11877     57/push-edi
11878     # edi = out
11879     8b/-> *(ebp+0x20) 7/r32/edi
11880     # out = new stmt-var
11881     (allocate *(ebp+8) *Stmt-var-size %edi)
11882     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
11883     (lookup *edi *(edi+4))  # => eax
11884     89/<- %ecx 0/r32/eax
11885     # out-addr->value = v
11886     8b/-> *(ebp+0xc) 0/r32/eax
11887     89/<- *ecx 0/r32/eax  # Stmt-var-value
11888     8b/-> *(ebp+0x10) 0/r32/eax
11889     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
11890     # out-addr->is-deref? = is-deref?
11891     8b/-> *(ebp+0x1c) 0/r32/eax
11892     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
11893     # if (vars == null) return result
11894     81 7/subop/compare *(ebp+0x14) 0/imm32/null
11895     74/jump-if-= $append-stmt-var:end/disp8
11896     # otherwise append
11897     # var curr/eax: (addr stmt-var) = lookup(vars)
11898     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
11899     # while (curr->next != null) curr = curr->next
11900     {
11901       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
11902       74/jump-if-= break/disp8
11903       # curr = lookup(curr->next)
11904       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
11905       #
11906       eb/jump loop/disp8
11907     }
11908     # curr->next = out
11909     8b/-> *edi 1/r32/ecx
11910     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
11911     8b/-> *(edi+4) 1/r32/ecx
11912     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
11913     # out = vars
11914     8b/-> *(ebp+0x14) 1/r32/ecx
11915     89/<- *edi 1/r32/ecx
11916     8b/-> *(ebp+0x18) 1/r32/ecx
11917     89/<- *(edi+4) 1/r32/ecx
11918 $append-stmt-var:end:
11919     # . restore registers
11920     5f/pop-to-edi
11921     59/pop-to-ecx
11922     58/pop-to-eax
11923     # . epilogue
11924     89/<- %esp 5/r32/ebp
11925     5d/pop-to-ebp
11926     c3/return
11927 
11928 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
11929     # . prologue
11930     55/push-ebp
11931     89/<- %ebp 4/r32/esp
11932     # . save registers
11933     50/push-eax
11934     56/push-esi
11935     # esi = block
11936     8b/-> *(ebp+0xc) 6/r32/esi
11937     # block->stmts = append(x, block->stmts)
11938     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
11939     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
11940 $append-to-block:end:
11941     # . restore registers
11942     5e/pop-to-esi
11943     58/pop-to-eax
11944     # . epilogue
11945     89/<- %esp 5/r32/ebp
11946     5d/pop-to-ebp
11947     c3/return
11948 
11949 ## Parsing types
11950 # We need to create metadata on user-defined types, and we need to use this
11951 # metadata as we parse instructions.
11952 # However, we also want to allow types to be used before their definitions.
11953 # This means we can't ever assume any type data structures exist.
11954 
11955 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
11956     # . prologue
11957     55/push-ebp
11958     89/<- %ebp 4/r32/esp
11959     # . save registers
11960     50/push-eax
11961     56/push-esi
11962     # var container-type/esi: type-id
11963     (container-type *(ebp+8))  # => eax
11964     89/<- %esi 0/r32/eax
11965     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
11966     68/push 0/imm32
11967     68/push 0/imm32
11968     89/<- %eax 4/r32/esp
11969     (find-or-create-typeinfo %esi %eax)
11970     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
11971     (lookup *eax *(eax+4))  # => eax
11972     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
11973 #?     (write-buffered Stderr "constant: ")
11974 #?     (write-slice-buffered Stderr *(ebp+0xc))
11975 #?     (write-buffered Stderr Newline)
11976 #?     (flush Stderr)
11977     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
11978 #?     8b/-> *(ebp+0x10) 0/r32/eax
11979 #?     (write-buffered Stderr "@")
11980 #?     (lookup *eax *(eax+4))
11981 #?     (write-int32-hex-buffered Stderr %eax)
11982 #?     (lookup *eax *(eax+4))
11983 #?     (write-buffered Stderr %eax)
11984 #?     (write-buffered Stderr Newline)
11985 #?     (flush Stderr)
11986 #?     (write-buffered Stderr "offset: ")
11987 #?     8b/-> *(eax+0x14) 0/r32/eax
11988 #?     (write-int32-hex-buffered Stderr %eax)
11989 #?     (write-buffered Stderr Newline)
11990 #?     (flush Stderr)
11991 $lookup-or-create-constant:end:
11992     # . reclaim locals
11993     81 0/subop/add %esp 8/imm32
11994     # . restore registers
11995     5e/pop-to-esi
11996     58/pop-to-eax
11997     # . epilogue
11998     89/<- %esp 5/r32/ebp
11999     5d/pop-to-ebp
12000     c3/return
12001 
12002 # if addr var:
12003 #   container->var->type->right->left->value
12004 # otherwise
12005 #   container->var->type->value
12006 container-type:  # container: (addr stmt-var) -> result/eax: type-id
12007     # . prologue
12008     55/push-ebp
12009     89/<- %ebp 4/r32/esp
12010     #
12011     8b/-> *(ebp+8) 0/r32/eax
12012     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
12013     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
12014     {
12015       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
12016       74/jump-if-= break/disp8
12017       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
12018       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
12019     }
12020     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
12021 $container-type:end:
12022     # . epilogue
12023     89/<- %esp 5/r32/ebp
12024     5d/pop-to-ebp
12025     c3/return
12026 
12027 is-container?:  # t: type-id -> result/eax: boolean
12028     # . prologue
12029     55/push-ebp
12030     89/<- %ebp 4/r32/esp
12031     #
12032     8b/-> *(ebp+8) 0/r32/eax
12033     c1/shift 4/subop/left %eax 2/imm8
12034     3b/compare 0/r32/eax *Primitive-type-ids
12035     0f 9d/set-if->= %al
12036     81 4/subop/and %eax 0xff/imm32
12037 $is-container?:end:
12038     # . epilogue
12039     89/<- %esp 5/r32/ebp
12040     5d/pop-to-ebp
12041     c3/return
12042 
12043 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
12044     # . prologue
12045     55/push-ebp
12046     89/<- %ebp 4/r32/esp
12047     # . save registers
12048     50/push-eax
12049     51/push-ecx
12050     52/push-edx
12051     57/push-edi
12052     # edi = out
12053     8b/-> *(ebp+0xc) 7/r32/edi
12054     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
12055     68/push 0/imm32
12056     68/push 0/imm32
12057     89/<- %ecx 4/r32/esp
12058     # find-typeinfo(t, out)
12059     (find-typeinfo *(ebp+8) %edi)
12060     {
12061       # if (*out != 0) break
12062       81 7/subop/compare *edi 0/imm32
12063       0f 85/jump-if-!= break/disp32
12064 $find-or-create-typeinfo:create:
12065       # *out = allocate
12066       (allocate Heap *Typeinfo-size %edi)
12067       # var tmp/eax: (addr typeinfo) = lookup(*out)
12068       (lookup *edi *(edi+4))  # => eax
12069 #?     (write-buffered Stderr "created typeinfo at ")
12070 #?     (write-int32-hex-buffered Stderr %eax)
12071 #?     (write-buffered Stderr " for type-id ")
12072 #?     (write-int32-hex-buffered Stderr *(ebp+8))
12073 #?     (write-buffered Stderr Newline)
12074 #?     (flush Stderr)
12075       # tmp->id = t
12076       8b/-> *(ebp+8) 2/r32/edx
12077       89/<- *eax 2/r32/edx  # Typeinfo-id
12078       # tmp->fields = new table
12079       # . fields = new table
12080       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
12081       # . tmp->fields = fields
12082       8b/-> *ecx 2/r32/edx
12083       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
12084       8b/-> *(ecx+4) 2/r32/edx
12085       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
12086       # tmp->next = Program->types
12087       8b/-> *_Program-types 1/r32/ecx
12088       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
12089       8b/-> *_Program-types->payload 1/r32/ecx
12090       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
12091       # Program->types = out
12092       8b/-> *edi 1/r32/ecx
12093       89/<- *_Program-types 1/r32/ecx
12094       8b/-> *(edi+4) 1/r32/ecx
12095       89/<- *_Program-types->payload 1/r32/ecx
12096     }
12097 $find-or-create-typeinfo:end:
12098     # . reclaim locals
12099     81 0/subop/add %esp 8/imm32
12100     # . restore registers
12101     5f/pop-to-edi
12102     5a/pop-to-edx
12103     59/pop-to-ecx
12104     58/pop-to-eax
12105     # . epilogue
12106     89/<- %esp 5/r32/ebp
12107     5d/pop-to-ebp
12108     c3/return
12109 
12110 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
12111     # . prologue
12112     55/push-ebp
12113     89/<- %ebp 4/r32/esp
12114     # . save registers
12115     50/push-eax
12116     51/push-ecx
12117     52/push-edx
12118     57/push-edi
12119     # ecx = t
12120     8b/-> *(ebp+8) 1/r32/ecx
12121     # edi = out
12122     8b/-> *(ebp+0xc) 7/r32/edi
12123     # *out = Program->types
12124     8b/-> *_Program-types 0/r32/eax
12125     89/<- *edi 0/r32/eax
12126     8b/-> *_Program-types->payload 0/r32/eax
12127     89/<- *(edi+4) 0/r32/eax
12128     {
12129 $find-typeinfo:loop:
12130       # if (*out == 0) break
12131       81 7/subop/compare *edi 0/imm32
12132       74/jump-if-= break/disp8
12133 $find-typeinfo:check:
12134       # var tmp/eax: (addr typeinfo) = lookup(*out)
12135       (lookup *edi *(edi+4))  # => eax
12136       # if (tmp->id == t) break
12137       39/compare *eax 1/r32/ecx  # Typeinfo-id
12138       74/jump-if-= break/disp8
12139 $find-typeinfo:continue:
12140       # *out = tmp->next
12141       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
12142       89/<- *edi 2/r32/edx
12143       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
12144       89/<- *(edi+4) 2/r32/edx
12145       #
12146       eb/jump loop/disp8
12147     }
12148 $find-typeinfo:end:
12149     # . restore registers
12150     5f/pop-to-edi
12151     5a/pop-to-edx
12152     59/pop-to-ecx
12153     58/pop-to-eax
12154     # . epilogue
12155     89/<- %esp 5/r32/ebp
12156     5d/pop-to-ebp
12157     c3/return
12158 
12159 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
12160     # . prologue
12161     55/push-ebp
12162     89/<- %ebp 4/r32/esp
12163     # . save registers
12164     50/push-eax
12165     52/push-edx
12166     57/push-edi
12167     # var dest/edi: (handle typeinfo-entry)
12168     68/push 0/imm32
12169     68/push 0/imm32
12170     89/<- %edi 4/r32/esp
12171     # find-or-create-typeinfo-fields(T, f, dest)
12172     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
12173     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
12174     (lookup *edi *(edi+4))  # => eax
12175     89/<- %edi 0/r32/eax
12176     # if dest-addr->output-var doesn't exist, create it
12177     {
12178       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
12179       0f 85/jump-if-!= break/disp32
12180       # dest-addr->output-var = new var(dummy name, type, -1 offset)
12181       # . var name/eax: (handle array byte) = "field"
12182       68/push 0/imm32
12183       68/push 0/imm32
12184       89/<- %eax 4/r32/esp
12185       (slice-to-string Heap *(ebp+0xc) %eax)
12186       # . new var
12187       8d/copy-address *(edi+0xc) 2/r32/edx
12188       (new-var Heap  *eax *(eax+4)  %edx)
12189       # . reclaim name
12190       81 0/subop/add %esp 8/imm32
12191       # var result/edx: (addr var) = lookup(dest-addr->output-var)
12192       (lookup *(edi+0xc) *(edi+0x10))  # => eax
12193       89/<- %edx 0/r32/eax
12194       # result->type = new constant type
12195       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
12196       (allocate Heap *Type-tree-size %eax)
12197       (lookup *(edx+8) *(edx+0xc))  # => eax
12198       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
12199       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
12200       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
12201       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
12202       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
12203       # result->offset isn't filled out yet
12204       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
12205     }
12206     # out = dest-addr->output-var
12207     8b/-> *(ebp+0x10) 2/r32/edx
12208     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
12209     89/<- *edx 0/r32/eax
12210     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
12211     89/<- *(edx+4) 0/r32/eax
12212 $find-or-create-typeinfo-output-var:end:
12213     # . reclaim locals
12214     81 0/subop/add %esp 8/imm32
12215     # . restore registers
12216     5f/pop-to-edi
12217     5a/pop-to-edx
12218     58/pop-to-eax
12219     # . epilogue
12220     89/<- %esp 5/r32/ebp
12221     5d/pop-to-ebp
12222     c3/return
12223 
12224 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
12225     # . prologue
12226     55/push-ebp
12227     89/<- %ebp 4/r32/esp
12228     # . save registers
12229     50/push-eax
12230     56/push-esi
12231     57/push-edi
12232     # eax = lookup(T->fields)
12233     8b/-> *(ebp+8) 0/r32/eax
12234     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
12235     # edi = out
12236     8b/-> *(ebp+0x10) 7/r32/edi
12237     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
12238     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
12239     89/<- %esi 0/r32/eax
12240     # if src doesn't exist, allocate it
12241     {
12242       81 7/subop/compare *esi 0/imm32
12243       75/jump-if-!= break/disp8
12244       (allocate Heap *Typeinfo-entry-size %esi)
12245 #?       (write-buffered Stderr "handle at ")
12246 #?       (write-int32-hex-buffered Stderr %esi)
12247 #?       (write-buffered Stderr ": ")
12248 #?       (write-int32-hex-buffered Stderr *esi)
12249 #?       (write-buffered Stderr " ")
12250 #?       (write-int32-hex-buffered Stderr *(esi+4))
12251 #?       (write-buffered Stderr Newline)
12252 #?       (flush Stderr)
12253 #?       (lookup *esi *(esi+4))
12254 #?       (write-buffered Stderr "created typeinfo fields at ")
12255 #?       (write-int32-hex-buffered Stderr %esi)
12256 #?       (write-buffered Stderr " for ")
12257 #?       (write-int32-hex-buffered Stderr *(ebp+8))
12258 #?       (write-buffered Stderr Newline)
12259 #?       (flush Stderr)
12260     }
12261     # *out = src
12262     # . *edi = *src
12263     8b/-> *esi 0/r32/eax
12264     89/<- *edi 0/r32/eax
12265     8b/-> *(esi+4) 0/r32/eax
12266     89/<- *(edi+4) 0/r32/eax
12267 $find-or-create-typeinfo-fields:end:
12268     # . restore registers
12269     5f/pop-to-edi
12270     5e/pop-to-esi
12271     58/pop-to-eax
12272     # . epilogue
12273     89/<- %esp 5/r32/ebp
12274     5d/pop-to-ebp
12275     c3/return
12276 
12277 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
12278     # pseudocode:
12279     #   var line: (stream byte 512)
12280     #   curr-index = 0
12281     #   while true
12282     #     clear-stream(line)
12283     #     read-line-buffered(in, line)
12284     #     if line->write == 0
12285     #       abort
12286     #     word-slice = next-mu-token(line)
12287     #     if slice-empty?(word-slice)               # end of line
12288     #       continue
12289     #     if slice-equal?(word-slice, "}")
12290     #       break
12291     #     var v: (handle var) = parse-var-with-type(word-slice, line)
12292     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
12293     #     TODO: ensure that r->first is null
12294     #     r->index = curr-index
12295     #     curr-index++
12296     #     r->input-var = v
12297     #     if r->output-var == 0
12298     #       r->output-var = new literal
12299     #     TODO: ensure nothing else in line
12300     # t->total-size-in-bytes = -2 (not yet initialized)
12301     #
12302     # . prologue
12303     55/push-ebp
12304     89/<- %ebp 4/r32/esp
12305     # var curr-index: int at *(ebp-4)
12306     68/push 0/imm32
12307     # . save registers
12308     50/push-eax
12309     51/push-ecx
12310     52/push-edx
12311     53/push-ebx
12312     56/push-esi
12313     57/push-edi
12314     # edi = t
12315     8b/-> *(ebp+0xc) 7/r32/edi
12316     # var line/ecx: (stream byte 512)
12317     81 5/subop/subtract %esp 0x200/imm32
12318     68/push 0x200/imm32/size
12319     68/push 0/imm32/read
12320     68/push 0/imm32/write
12321     89/<- %ecx 4/r32/esp
12322     # var word-slice/edx: slice
12323     68/push 0/imm32/end
12324     68/push 0/imm32/start
12325     89/<- %edx 4/r32/esp
12326     # var v/esi: (handle var)
12327     68/push 0/imm32
12328     68/push 0/imm32
12329     89/<- %esi 4/r32/esp
12330     # var r/ebx: (handle typeinfo-entry)
12331     68/push 0/imm32
12332     68/push 0/imm32
12333     89/<- %ebx 4/r32/esp
12334     {
12335 $populate-mu-type:line-loop:
12336       (clear-stream %ecx)
12337       (read-line-buffered *(ebp+8) %ecx)
12338       # if (line->write == 0) abort
12339       81 7/subop/compare *ecx 0/imm32
12340       0f 84/jump-if-= $populate-mu-type:error1/disp32
12341 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
12347       (next-mu-token %ecx %edx)
12348       # if slice-empty?(word-slice) continue
12349       (slice-empty? %edx)  # => eax
12350       3d/compare-eax-and 0/imm32
12351       0f 85/jump-if-!= loop/disp32
12352       # if slice-equal?(word-slice, "}") break
12353       (slice-equal? %edx "}")
12354       3d/compare-eax-and 0/imm32
12355       0f 85/jump-if-!= break/disp32
12356 $populate-mu-type:parse-element:
12357       # v = parse-var-with-type(word-slice, first-line)
12358       # must do this first to strip the trailing ':' from word-slice before
12359       # using it in find-or-create-typeinfo-fields below
12360       # TODO: clean up that mutation in parse-var-with-type
12361       (parse-var-with-type %edx %ecx %esi *(ebp+0x10) *(ebp+0x14))
12362       # if v is an addr, abort
12363       (lookup *esi *(esi+4))  # => eax
12364       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
12365       (is-mu-addr-type? %eax)  # => eax
12366       3d/compare-eax-and 0/imm32/false
12367       0f 85/jump-if-!= $populate-mu-type:error2/disp32
12368       # if v is an array, abort  (we could support it, but initialization gets complex)
12369       (lookup *esi *(esi+4))  # => eax
12370       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
12371       (is-mu-array-type? %eax)  # => eax
12372       3d/compare-eax-and 0/imm32/false
12373       0f 85/jump-if-!= $populate-mu-type:error3/disp32
12374       # if v is a byte, abort
12375       (lookup *esi *(esi+4))  # => eax
12376       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
12377       (is-simple-mu-type? %eax 8)  # byte => eax
12378       3d/compare-eax-and 0/imm32/false
12379       0f 85/jump-if-!= $populate-mu-type:error4/disp32
12380       # if v is a slice, abort
12381       (lookup *esi *(esi+4))  # => eax
12382       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
12383       (is-simple-mu-type? %eax 0xc)  # slice => eax
12384       3d/compare-eax-and 0/imm32/false
12385       0f 85/jump-if-!= $populate-mu-type:error5/disp32
12386       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
12387       (lookup *esi *(esi+4))  # => eax
12388       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
12389       (is-mu-stream-type? %eax)  # => eax
12390       3d/compare-eax-and 0/imm32/false
12391       0f 85/jump-if-!= $populate-mu-type:error6/disp32
12392       # var tmp/ecx
12393       51/push-ecx
12394 $populate-mu-type:create-typeinfo-fields:
12395       # var r/ebx: (handle typeinfo-entry)
12396       (find-or-create-typeinfo-fields %edi %edx %ebx)
12397       # r->index = curr-index
12398       (lookup *ebx *(ebx+4))  # => eax
12399       8b/-> *(ebp-4) 1/r32/ecx
12400 #?       (write-buffered Stderr "saving index ")
12401 #?       (write-int32-hex-buffered Stderr %ecx)
12402 #?       (write-buffered Stderr " at ")
12403 #?       (write-int32-hex-buffered Stderr %edi)
12404 #?       (write-buffered Stderr Newline)
12405 #?       (flush Stderr)
12406       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
12407       # ++curr-index
12408       ff 0/subop/increment *(ebp-4)
12409 $populate-mu-type:set-input-type:
12410       # r->input-var = v
12411       8b/-> *esi 1/r32/ecx
12412       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
12413       8b/-> *(esi+4) 1/r32/ecx
12414       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
12415       # restore line
12416       59/pop-to-ecx
12417       {
12418 $populate-mu-type:create-output-type:
12419         # if (r->output-var == 0) create a new var with some placeholder data
12420         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
12421         75/jump-if-!= break/disp8
12422         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
12423         (new-literal Heap %edx %eax)
12424       }
12425       e9/jump loop/disp32
12426     }
12427 $populate-mu-type:invalidate-total-size-in-bytes:
12428     # Offsets and total size may not be accurate here since we may not yet
12429     # have encountered the element types.
12430     # We'll recompute them separately after parsing the entire program.
12431     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
12432 $populate-mu-type:end:
12433     # . reclaim locals
12434     81 0/subop/add %esp 0x224/imm32
12435     # . restore registers
12436     5f/pop-to-edi
12437     5e/pop-to-esi
12438     5b/pop-to-ebx
12439     5a/pop-to-edx
12440     59/pop-to-ecx
12441     58/pop-to-eax
12442     # reclaim curr-index
12443     81 0/subop/add %esp 4/imm32
12444     # . epilogue
12445     89/<- %esp 5/r32/ebp
12446     5d/pop-to-ebp
12447     c3/return
12448 
12449 $populate-mu-type:error1:
12450     # error("incomplete type definition '" t->name "'\n")
12451     (write-buffered *(ebp+0x10) "incomplete type definition '")
12452     (type-name *edi)  # Typeinfo-id => eax
12453     (write-buffered *(ebp+0x10) %eax)
12454     (write-buffered *(ebp+0x10) "\n")
12455     (flush *(ebp+0x10))
12456     (stop *(ebp+0x14) 1)
12457     # never gets here
12458 
12459 $populate-mu-type:error2:
12460     (write-buffered *(ebp+0x10) "type ")
12461     (type-name *edi)  # Typeinfo-id => eax
12462     (write-buffered *(ebp+0x10) %eax)
12463     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
12464     (flush *(ebp+0x10))
12465     (stop *(ebp+0x14) 1)
12466     # never gets here
12467 
12468 $populate-mu-type:error3:
12469     (write-buffered *(ebp+0x10) "type ")
12470     (type-name *edi)  # Typeinfo-id => eax
12471     (write-buffered *(ebp+0x10) %eax)
12472     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
12473     (flush *(ebp+0x10))
12474     (stop *(ebp+0x14) 1)
12475     # never gets here
12476 
12477 $populate-mu-type:error4:
12478     (write-buffered *(ebp+0x10) "type ")
12479     (type-name *edi)  # Typeinfo-id => eax
12480     (write-buffered *(ebp+0x10) %eax)
12481     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
12482     (flush *(ebp+0x10))
12483     (stop *(ebp+0x14) 1)
12484     # never gets here
12485 
12486 $populate-mu-type:error5:
12487     (write-buffered *(ebp+0x10) "type ")
12488     (type-name *edi)  # Typeinfo-id => eax
12489     (write-buffered *(ebp+0x10) %eax)
12490     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
12491     (flush *(ebp+0x10))
12492     (stop *(ebp+0x14) 1)
12493     # never gets here
12494 
12495 $populate-mu-type:error6:
12496     (write-buffered *(ebp+0x10) "type ")
12497     (type-name *edi)  # Typeinfo-id => eax
12498     (write-buffered *(ebp+0x10) %eax)
12499     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
12500     (flush *(ebp+0x10))
12501     (stop *(ebp+0x14) 1)
12502     # never gets here
12503 
12504 type-name:  # index: int -> result/eax: (addr array byte)
12505     # . prologue
12506     55/push-ebp
12507     89/<- %ebp 4/r32/esp
12508     #
12509     (index Type-id *(ebp+8))
12510 $type-name:end:
12511     # . epilogue
12512     89/<- %esp 5/r32/ebp
12513     5d/pop-to-ebp
12514     c3/return
12515 
12516 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
12517     # . prologue
12518     55/push-ebp
12519     89/<- %ebp 4/r32/esp
12520     # . save registers
12521     56/push-esi
12522     # TODO: bounds-check index
12523     # esi = arr
12524     8b/-> *(ebp+8) 6/r32/esi
12525     # eax = index
12526     8b/-> *(ebp+0xc) 0/r32/eax
12527     # eax = *(arr + 12 + index)
12528     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
12529 $index:end:
12530     # . restore registers
12531     5e/pop-to-esi
12532     # . epilogue
12533     89/<- %esp 5/r32/ebp
12534     5d/pop-to-ebp
12535     c3/return
12536 
12537 #######################################################
12538 # Compute type sizes
12539 #######################################################
12540 
12541 # Compute the sizes of all user-defined types.
12542 # We'll need the sizes of their elements, which may be other user-defined
12543 # types, which we will compute as needed.
12544 
12545 # Initially, all user-defined types have their sizes set to -2 (invalid)
12546 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
12547     # . prologue
12548     55/push-ebp
12549     89/<- %ebp 4/r32/esp
12550 $populate-mu-type-sizes:total-sizes:
12551     # var curr/eax: (addr typeinfo) = lookup(Program->types)
12552     (lookup *_Program-types *_Program-types->payload)  # => eax
12553     {
12554       # if (curr == null) break
12555       3d/compare-eax-and 0/imm32/null
12556       74/jump-if-= break/disp8
12557       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
12558       # curr = lookup(curr->next)
12559       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
12560       eb/jump loop/disp8
12561     }
12562 $populate-mu-type-sizes:offsets:
12563     # curr = *Program->types
12564     (lookup *_Program-types *_Program-types->payload)  # => eax
12565     {
12566       # if (curr == null) break
12567       3d/compare-eax-and 0/imm32/null
12568       74/jump-if-= break/disp8
12569       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
12570       # curr = curr->next
12571       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
12572       eb/jump loop/disp8
12573     }
12574 $populate-mu-type-sizes:end:
12575     # . epilogue
12576     89/<- %esp 5/r32/ebp
12577     5d/pop-to-ebp
12578     c3/return
12579 
12580 # compute sizes of all fields, recursing as necessary
12581 # sum up all their sizes to arrive at total size
12582 # fields may be out of order, but that doesn't affect the answer
12583 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
12584     # . prologue
12585     55/push-ebp
12586     89/<- %ebp 4/r32/esp
12587     # . save registers
12588     50/push-eax
12589     51/push-ecx
12590     52/push-edx
12591     56/push-esi
12592     57/push-edi
12593     # esi = T
12594     8b/-> *(ebp+8) 6/r32/esi
12595     # if T is already computed, return
12596     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
12597     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
12598     # if T is being computed, abort
12599     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
12600     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
12601     # tag T (-2 to -1) to avoid infinite recursion
12602     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
12603     # var total-size/edi: int = 0
12604     bf/copy-to-edi 0/imm32
12605     # - for every field, if it's a user-defined type, compute its size
12606     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
12607     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
12608     89/<- %ecx 0/r32/eax
12609     # var table-size/edx: int = table->write
12610     8b/-> *ecx 2/r32/edx  # stream-write
12611     # var curr/ecx: (addr table_row) = table->data
12612     8d/copy-address *(ecx+0xc) 1/r32/ecx
12613     # var max/edx: (addr table_row) = table->data + table->write
12614     8d/copy-address *(ecx+edx) 2/r32/edx
12615     {
12616 $populate-mu-type-sizes-in-type:loop:
12617       # if (curr >= max) break
12618       39/compare %ecx 2/r32/edx
12619       73/jump-if-addr>= break/disp8
12620       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
12621       (lookup *(ecx+8) *(ecx+0xc))  # => eax
12622       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
12623       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
12624       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
12625       # compute size of t->input-var
12626       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
12627       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
12628       # result += eax
12629       01/add-to %edi 0/r32/eax
12630       # curr += row-size
12631       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
12632       #
12633       eb/jump loop/disp8
12634     }
12635     # - save result
12636     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
12637 $populate-mu-type-sizes-in-type:end:
12638     # . restore registers
12639     5f/pop-to-edi
12640     5e/pop-to-esi
12641     5a/pop-to-edx
12642     59/pop-to-ecx
12643     58/pop-to-eax
12644     # . epilogue
12645     89/<- %esp 5/r32/ebp
12646     5d/pop-to-ebp
12647     c3/return
12648 
12649 $populate-mu-type-sizes-in-type:abort:
12650     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
12651     (flush *(ebp+0xc))
12652     (stop *(ebp+0x10) 1)
12653     # never gets here
12654 
12655 # Analogous to size-of, except we need to compute what size-of can just read
12656 # off the right data structures.
12657 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
12658     # . prologue
12659     55/push-ebp
12660     89/<- %ebp 4/r32/esp
12661     # . push registers
12662     51/push-ecx
12663     # var t/ecx: (addr type-tree) = lookup(v->type)
12664     8b/-> *(ebp+8) 1/r32/ecx
12665     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
12666     89/<- %ecx 0/r32/eax
12667     # if (t->is-atom == false) t = lookup(t->left)
12668     {
12669       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
12670       75/jump-if-!= break/disp8
12671       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
12672       89/<- %ecx 0/r32/eax
12673     }
12674     # TODO: ensure t is an atom
12675     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
12676 $compute-size-of-var:end:
12677     # . restore registers
12678     59/pop-to-ecx
12679     # . epilogue
12680     89/<- %esp 5/r32/ebp
12681     5d/pop-to-ebp
12682     c3/return
12683 
12684 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
12685     # . prologue
12686     55/push-ebp
12687     89/<- %ebp 4/r32/esp
12688     # . save registers
12689     51/push-ecx
12690     # var out/ecx: (handle typeinfo)
12691     68/push 0/imm32
12692     68/push 0/imm32
12693     89/<- %ecx 4/r32/esp
12694     # eax = t
12695     8b/-> *(ebp+8) 0/r32/eax
12696     # if t is a literal, return 0
12697     3d/compare-eax-and 0/imm32/literal
12698     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
12699     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
12700     3d/compare-eax-and 8/imm32/byte
12701     {
12702       75/jump-if-!= break/disp8
12703       b8/copy-to-eax 4/imm32
12704       eb/jump $compute-size-of-type-id:end/disp8
12705     }
12706     # if t is a handle, return 8
12707     3d/compare-eax-and 4/imm32/handle
12708     {
12709       75/jump-if-!= break/disp8
12710       b8/copy-to-eax 8/imm32
12711       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
12712     }
12713     # if t is a slice, return 8
12714     3d/compare-eax-and 0xc/imm32/slice
12715     {
12716       75/jump-if-!= break/disp8
12717       b8/copy-to-eax 8/imm32
12718       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
12719     }
12720     # if t is a user-defined type, compute its size
12721     # TODO: support non-atom type
12722     (find-typeinfo %eax %ecx)
12723     {
12724       81 7/subop/compare *ecx 0/imm32
12725       74/jump-if-= break/disp8
12726 $compute-size-of-type-id:user-defined:
12727       (lookup *ecx *(ecx+4))  # => eax
12728       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
12729       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
12730       eb/jump $compute-size-of-type-id:end/disp8
12731     }
12732     # otherwise return the word size
12733     b8/copy-to-eax 4/imm32
12734 $compute-size-of-type-id:end:
12735     # . reclaim locals
12736     81 0/subop/add %esp 8/imm32
12737     # . restore registers
12738     59/pop-to-ecx
12739     # . epilogue
12740     89/<- %esp 5/r32/ebp
12741     5d/pop-to-ebp
12742     c3/return
12743 
12744 # at this point we have total sizes for all user-defined types
12745 # compute offsets for each element
12746 # complication: fields may be out of order
12747 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
12748     # . prologue
12749     55/push-ebp
12750     89/<- %ebp 4/r32/esp
12751     # . save registers
12752     50/push-eax
12753     51/push-ecx
12754     52/push-edx
12755     53/push-ebx
12756     56/push-esi
12757     57/push-edi
12758 #?     (dump-typeinfos "aaa\n")
12759     # var curr-offset/edi: int = 0
12760     bf/copy-to-edi 0/imm32
12761     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
12762     8b/-> *(ebp+8) 1/r32/ecx
12763     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
12764     89/<- %ecx 0/r32/eax
12765     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
12766     8b/-> *ecx 2/r32/edx  # stream-write
12767     c1 5/subop/shift-right-logical  %edx 4/imm8
12768     # var i/ebx: int = 0
12769     bb/copy-to-ebx 0/imm32
12770     {
12771 $populate-mu-type-offsets:loop:
12772       39/compare %ebx 2/r32/edx
12773       0f 8d/jump-if->= break/disp32
12774 #?       (write-buffered Stderr "looking up index ")
12775 #?       (write-int32-hex-buffered Stderr %ebx)
12776 #?       (write-buffered Stderr " in ")
12777 #?       (write-int32-hex-buffered Stderr *(ebp+8))
12778 #?       (write-buffered Stderr Newline)
12779 #?       (flush Stderr)
12780       # var v/esi: (addr typeinfo-entry)
12781       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
12782       89/<- %esi 0/r32/eax
12783       # if v is null, silently move on; we'll emit a nice error message while type-checking
12784       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
12785       74/jump-if-= $populate-mu-type-offsets:end/disp8
12786       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
12787       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
12788       74/jump-if-= $populate-mu-type-offsets:end/disp8
12789       # v->output-var->offset = curr-offset
12790       # . eax: (addr var)
12791       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
12792       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
12793       # curr-offset += size-of(v->input-var)
12794       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
12795       (size-of %eax)  # => eax
12796       01/add-to %edi 0/r32/eax
12797       # ++i
12798       43/increment-ebx
12799       e9/jump loop/disp32
12800     }
12801 $populate-mu-type-offsets:end:
12802     # . restore registers
12803     5f/pop-to-edi
12804     5e/pop-to-esi
12805     5b/pop-to-ebx
12806     5a/pop-to-edx
12807     59/pop-to-ecx
12808     58/pop-to-eax
12809     # . epilogue
12810     89/<- %esp 5/r32/ebp
12811     5d/pop-to-ebp
12812     c3/return
12813 
12814 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)
12815     # . prologue
12816     55/push-ebp
12817     89/<- %ebp 4/r32/esp
12818     # . save registers
12819     51/push-ecx
12820     52/push-edx
12821     53/push-ebx
12822     56/push-esi
12823     57/push-edi
12824     # esi = table
12825     8b/-> *(ebp+8) 6/r32/esi
12826     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
12827     8d/copy-address *(esi+0xc) 1/r32/ecx
12828     # var max/edx: (addr byte) = &table->data[table->write]
12829     8b/-> *esi 2/r32/edx
12830     8d/copy-address *(ecx+edx) 2/r32/edx
12831     {
12832 $locate-typeinfo-entry-with-index:loop:
12833       39/compare %ecx 2/r32/edx
12834       73/jump-if-addr>= break/disp8
12835       # var v/eax: (addr typeinfo-entry)
12836       (lookup *(ecx+8) *(ecx+0xc))  # => eax
12837       # if (v->index == idx) return v
12838       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
12839 #?       (write-buffered Stderr "comparing ")
12840 #?       (write-int32-hex-buffered Stderr %ebx)
12841 #?       (write-buffered Stderr " and ")
12842 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
12843 #?       (write-buffered Stderr Newline)
12844 #?       (flush Stderr)
12845       39/compare *(ebp+0xc) 3/r32/ebx
12846       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
12847       # curr += Typeinfo-entry-size
12848       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
12849       #
12850       eb/jump loop/disp8
12851     }
12852     # return 0
12853     b8/copy-to-eax 0/imm32
12854 $locate-typeinfo-entry-with-index:end:
12855 #?     (write-buffered Stderr "returning ")
12856 #?     (write-int32-hex-buffered Stderr %eax)
12857 #?     (write-buffered Stderr Newline)
12858 #?     (flush Stderr)
12859     # . restore registers
12860     5f/pop-to-edi
12861     5e/pop-to-esi
12862     5b/pop-to-ebx
12863     5a/pop-to-edx
12864     59/pop-to-ecx
12865     # . epilogue
12866     89/<- %esp 5/r32/ebp
12867     5d/pop-to-ebp
12868     c3/return
12869 
12870 dump-typeinfos:  # hdr: (addr array byte)
12871     # . prologue
12872     55/push-ebp
12873     89/<- %ebp 4/r32/esp
12874     # . save registers
12875     50/push-eax
12876     #
12877     (write-buffered Stderr *(ebp+8))
12878     (flush Stderr)
12879     # var curr/eax: (addr typeinfo) = lookup(Program->types)
12880     (lookup *_Program-types *_Program-types->payload)  # => eax
12881     {
12882       # if (curr == null) break
12883       3d/compare-eax-and 0/imm32
12884       74/jump-if-= break/disp8
12885       (write-buffered Stderr "---\n")
12886       (flush Stderr)
12887       (dump-typeinfo %eax)
12888       # curr = lookup(curr->next)
12889       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
12890       eb/jump loop/disp8
12891     }
12892 $dump-typeinfos:end:
12893     # . restore registers
12894     58/pop-to-eax
12895     # . epilogue
12896     89/<- %esp 5/r32/ebp
12897     5d/pop-to-ebp
12898     c3/return
12899 
12900 dump-typeinfo:  # in: (addr typeinfo)
12901     # . prologue
12902     55/push-ebp
12903     89/<- %ebp 4/r32/esp
12904     # . save registers
12905     50/push-eax
12906     51/push-ecx
12907     52/push-edx
12908     53/push-ebx
12909     56/push-esi
12910     57/push-edi
12911     # esi = in
12912     8b/-> *(ebp+8) 6/r32/esi
12913     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
12914     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
12915     89/<- %ecx 0/r32/eax
12916     (write-buffered Stderr "id:")
12917     (write-int32-hex-buffered Stderr *esi)
12918     (write-buffered Stderr "\n")
12919     (write-buffered Stderr "fields @ ")
12920     (write-int32-hex-buffered Stderr %ecx)
12921     (write-buffered Stderr Newline)
12922     (flush Stderr)
12923     (write-buffered Stderr "  write: ")
12924     (write-int32-hex-buffered Stderr *ecx)
12925     (write-buffered Stderr Newline)
12926     (flush Stderr)
12927     (write-buffered Stderr "  read: ")
12928     (write-int32-hex-buffered Stderr *(ecx+4))
12929     (write-buffered Stderr Newline)
12930     (flush Stderr)
12931     (write-buffered Stderr "  size: ")
12932     (write-int32-hex-buffered Stderr *(ecx+8))
12933     (write-buffered Stderr Newline)
12934     (flush Stderr)
12935     # var table-size/edx: int = table->write
12936     8b/-> *ecx 2/r32/edx  # stream-write
12937     # var curr/ecx: (addr table_row) = table->data
12938     8d/copy-address *(ecx+0xc) 1/r32/ecx
12939     # var max/edx: (addr table_row) = table->data + table->write
12940     8d/copy-address *(ecx+edx) 2/r32/edx
12941     {
12942 $dump-typeinfo:loop:
12943       # if (curr >= max) break
12944       39/compare %ecx 2/r32/edx
12945       0f 83/jump-if-addr>= break/disp32
12946       (write-buffered Stderr "  row:\n")
12947       (write-buffered Stderr "    key: ")
12948       (write-int32-hex-buffered Stderr *ecx)
12949       (write-buffered Stderr ",")
12950       (write-int32-hex-buffered Stderr *(ecx+4))
12951       (write-buffered Stderr " = '")
12952       (lookup *ecx *(ecx+4))
12953       (write-buffered Stderr %eax)
12954       (write-buffered Stderr "' @ ")
12955       (write-int32-hex-buffered Stderr %eax)
12956       (write-buffered Stderr Newline)
12957       (flush Stderr)
12958       (write-buffered Stderr "    value: ")
12959       (write-int32-hex-buffered Stderr *(ecx+8))
12960       (write-buffered Stderr ",")
12961       (write-int32-hex-buffered Stderr *(ecx+0xc))
12962       (write-buffered Stderr " = typeinfo-entry@")
12963       (lookup *(ecx+8) *(ecx+0xc))
12964       (write-int32-hex-buffered Stderr %eax)
12965       (write-buffered Stderr Newline)
12966       (flush Stderr)
12967       (write-buffered Stderr "        input var@")
12968       (dump-var 5 %eax)
12969       (lookup *(ecx+8) *(ecx+0xc))
12970       (write-buffered Stderr "        index: ")
12971       (write-int32-hex-buffered Stderr *(eax+8))
12972       (write-buffered Stderr Newline)
12973       (flush Stderr)
12974       (write-buffered Stderr "        output var@")
12975       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
12976       (dump-var 5 %eax)
12977       (flush Stderr)
12978       # curr += row-size
12979       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
12980       #
12981       e9/jump loop/disp32
12982     }
12983 $dump-typeinfo:end:
12984     # . restore registers
12985     5f/pop-to-edi
12986     5e/pop-to-esi
12987     5b/pop-to-ebx
12988     5a/pop-to-edx
12989     59/pop-to-ecx
12990     58/pop-to-eax
12991     # . epilogue
12992     89/<- %esp 5/r32/ebp
12993     5d/pop-to-ebp
12994     c3/return
12995 
12996 dump-var:  # indent: int, v: (addr handle var)
12997     # . prologue
12998     55/push-ebp
12999     89/<- %ebp 4/r32/esp
13000     # . save registers
13001     50/push-eax
13002     53/push-ebx
13003     # eax = v
13004     8b/-> *(ebp+0xc) 0/r32/eax
13005     #
13006     (write-int32-hex-buffered Stderr *eax)
13007     (write-buffered Stderr ",")
13008     (write-int32-hex-buffered Stderr *(eax+4))
13009     (write-buffered Stderr "->")
13010     (lookup *eax *(eax+4))
13011     (write-int32-hex-buffered Stderr %eax)
13012     (write-buffered Stderr Newline)
13013     (flush Stderr)
13014     {
13015       3d/compare-eax-and 0/imm32
13016       0f 84/jump-if-= break/disp32
13017       (emit-indent Stderr *(ebp+8))
13018       (write-buffered Stderr "name: ")
13019       89/<- %ebx 0/r32/eax
13020       (write-int32-hex-buffered Stderr *ebx)  # Var-name
13021       (write-buffered Stderr ",")
13022       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
13023       (write-buffered Stderr "->")
13024       (lookup *ebx *(ebx+4))  # Var-name
13025       (write-int32-hex-buffered Stderr %eax)
13026       {
13027         3d/compare-eax-and 0/imm32
13028         74/jump-if-= break/disp8
13029         (write-buffered Stderr Space)
13030         (write-buffered Stderr %eax)
13031       }
13032       (write-buffered Stderr Newline)
13033       (flush Stderr)
13034       (emit-indent Stderr *(ebp+8))
13035       (write-buffered Stderr "block depth: ")
13036       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
13037       (write-buffered Stderr Newline)
13038       (flush Stderr)
13039       (emit-indent Stderr *(ebp+8))
13040       (write-buffered Stderr "stack offset: ")
13041       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
13042       (write-buffered Stderr Newline)
13043       (flush Stderr)
13044       (emit-indent Stderr *(ebp+8))
13045       (write-buffered Stderr "reg: ")
13046       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
13047       (write-buffered Stderr ",")
13048       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
13049       (write-buffered Stderr "->")
13050       (flush Stderr)
13051       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
13052       (write-int32-hex-buffered Stderr %eax)
13053       {
13054         3d/compare-eax-and 0/imm32
13055         74/jump-if-= break/disp8
13056         (write-buffered Stderr Space)
13057         (write-buffered Stderr %eax)
13058       }
13059       (write-buffered Stderr Newline)
13060       (flush Stderr)
13061     }
13062 $dump-var:end:
13063     # . restore registers
13064     5b/pop-to-ebx
13065     58/pop-to-eax
13066     # . epilogue
13067     89/<- %esp 5/r32/ebp
13068     5d/pop-to-ebp
13069     c3/return
13070 
13071 #######################################################
13072 # Type-checking
13073 #######################################################
13074 
13075 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
13076     # . prologue
13077     55/push-ebp
13078     89/<- %ebp 4/r32/esp
13079     # . save registers
13080     50/push-eax
13081     # var curr/eax: (addr function) = lookup(Program->functions)
13082     (lookup *_Program-functions *_Program-functions->payload)  # => eax
13083     {
13084 $check-mu-types:loop:
13085       # if (curr == null) break
13086       3d/compare-eax-and 0/imm32
13087       0f 84/jump-if-= break/disp32
13088 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
13096       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
13097       # curr = lookup(curr->next)
13098       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
13099       e9/jump loop/disp32
13100     }
13101 $check-mu-types:end:
13102     # . restore registers
13103     58/pop-to-eax
13104     # . epilogue
13105     89/<- %esp 5/r32/ebp
13106     5d/pop-to-ebp
13107     c3/return
13108 
13109 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13110     # . prologue
13111     55/push-ebp
13112     89/<- %ebp 4/r32/esp
13113     # . save registers
13114     50/push-eax
13115     # eax = f
13116     8b/-> *(ebp+8) 0/r32/eax
13117     # TODO: anything to check in header?
13118     # var body/eax: (addr block) = lookup(f->body)
13119     (lookup *(eax+0x18) *(eax+0x1c))  # Function-body Function-body => eax
13120     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
13121 $check-mu-function:end:
13122     # . restore registers
13123     58/pop-to-eax
13124     # . epilogue
13125     89/<- %esp 5/r32/ebp
13126     5d/pop-to-ebp
13127     c3/return
13128 
13129 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13130     # . prologue
13131     55/push-ebp
13132     89/<- %ebp 4/r32/esp
13133     # . save registers
13134     50/push-eax
13135     # eax = block
13136     8b/-> *(ebp+8) 0/r32/eax
13137     # var stmts/eax: (addr list stmt) = lookup(block->statements)
13138     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
13139     #
13140     {
13141 $check-mu-block:check-empty:
13142       3d/compare-eax-and 0/imm32
13143       0f 84/jump-if-= break/disp32
13144       # emit block->statements
13145       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13146     }
13147 $check-mu-block:end:
13148     # . restore registers
13149     58/pop-to-eax
13150     # . epilogue
13151     89/<- %esp 5/r32/ebp
13152     5d/pop-to-ebp
13153     c3/return
13154 
13155 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13156     # . prologue
13157     55/push-ebp
13158     89/<- %ebp 4/r32/esp
13159     # . save registers
13160     50/push-eax
13161     56/push-esi
13162     # esi = stmts
13163     8b/-> *(ebp+8) 6/r32/esi
13164     {
13165 $check-mu-stmt-list:loop:
13166       81 7/subop/compare %esi 0/imm32
13167       0f 84/jump-if-= break/disp32
13168       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
13169       (lookup *esi *(esi+4))  # List-value List-value => eax
13170       {
13171 $check-mu-stmt-list:check-for-block:
13172         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
13173         75/jump-if-!= break/disp8
13174 $check-mu-stmt-list:block:
13175         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13176         eb/jump $check-mu-stmt-list:continue/disp8
13177       }
13178       {
13179 $check-mu-stmt-list:check-for-stmt1:
13180         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
13181         0f 85/jump-if-!= break/disp32
13182 $check-mu-stmt-list:stmt1:
13183         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13184         eb/jump $check-mu-stmt-list:continue/disp8
13185       }
13186       {
13187 $check-mu-stmt-list:check-for-reg-var-def:
13188         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
13189         0f 85/jump-if-!= break/disp32
13190 $check-mu-stmt-list:reg-var-def:
13191         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13192         eb/jump $check-mu-stmt-list:continue/disp8
13193       }
13194 $check-mu-stmt-list:continue:
13195       # TODO: raise an error on unrecognized Stmt-tag
13196       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
13197       89/<- %esi 0/r32/eax
13198       e9/jump loop/disp32
13199     }
13200 $check-mu-stmt-list:end:
13201     # . restore registers
13202     5e/pop-to-esi
13203     58/pop-to-eax
13204     # . epilogue
13205     89/<- %esp 5/r32/ebp
13206     5d/pop-to-ebp
13207     c3/return
13208 
13209 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13210     # . prologue
13211     55/push-ebp
13212     89/<- %ebp 4/r32/esp
13213     # . save registers
13214     50/push-eax
13215     # - if stmt's operation matches a primitive, check against it
13216     (has-primitive-name? *(ebp+8))  # => eax
13217     3d/compare-eax-and 0/imm32/false
13218     {
13219       74/jump-if-= break/disp8
13220       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13221       e9/jump $check-mu-stmt:end/disp32
13222     }
13223     # - otherwise find a function to check against
13224     # var f/eax: (addr function) = lookup(*Program->functions)
13225     (lookup *_Program-functions *_Program-functions->payload)  # => eax
13226     (find-matching-function %eax *(ebp+8))  # => eax
13227     3d/compare-eax-and 0/imm32
13228     {
13229       74/jump-if-= break/disp8
13230       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13231       eb/jump $check-mu-stmt:end/disp8
13232     }
13233     # var f/eax: (addr function) = lookup(*Program->signatures)
13234     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
13235     (find-matching-function %eax *(ebp+8))  # => eax
13236     3d/compare-eax-and 0/imm32
13237     {
13238       74/jump-if-= break/disp8
13239       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13240       eb/jump $check-mu-stmt:end/disp8
13241     }
13242     # - otherwise abort
13243     e9/jump $check-mu-stmt:unknown-call/disp32
13244 $check-mu-stmt:end:
13245     # . restore registers
13246     58/pop-to-eax
13247     # . epilogue
13248     89/<- %esp 5/r32/ebp
13249     5d/pop-to-ebp
13250     c3/return
13251 
13252 $check-mu-stmt:unknown-call:
13253     (write-buffered *(ebp+0x10) "unknown function '")
13254     8b/-> *(ebp+8) 0/r32/eax
13255     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
13256     (write-buffered *(ebp+0x10) %eax)
13257     (write-buffered *(ebp+0x10) "'\n")
13258     (flush *(ebp+0x10))
13259     (stop *(ebp+0x14) 1)
13260     # never gets here
13261 
13262 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
13263     # . prologue
13264     55/push-ebp
13265     89/<- %ebp 4/r32/esp
13266     # . save registers
13267     51/push-ecx
13268     56/push-esi
13269     # var name/esi: (addr array byte) = lookup(stmt->operation)
13270     8b/-> *(ebp+8) 6/r32/esi
13271     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
13272     89/<- %esi 0/r32/eax
13273     # if (name == "get") return true
13274     (string-equal? %esi "get")  # => eax
13275     3d/compare-eax-and 0/imm32/false
13276     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13277     # if (name == "index") return true
13278     (string-equal? %esi "index")  # => eax
13279     3d/compare-eax-and 0/imm32/false
13280     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13281     # if (name == "length") return true
13282     (string-equal? %esi "length")  # => eax
13283     3d/compare-eax-and 0/imm32/false
13284     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13285     # if (name == "compute-offset") return true
13286     (string-equal? %esi "compute-offset")  # => eax
13287     3d/compare-eax-and 0/imm32/false
13288     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13289     # if (name == "copy-object") return true
13290     (string-equal? %esi "copy-object")  # => eax
13291     3d/compare-eax-and 0/imm32/false
13292     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13293     # if (name == "allocate") return true
13294     (string-equal? %esi "allocate")  # => eax
13295     3d/compare-eax-and 0/imm32/false
13296     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13297     # if (name == "populate") return true
13298     (string-equal? %esi "populate")  # => eax
13299     3d/compare-eax-and 0/imm32/false
13300     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13301     # if (name == "populate-stream") return true
13302     (string-equal? %esi "populate-stream")  # => eax
13303     3d/compare-eax-and 0/imm32/false
13304     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13305     # if (name == "read-from-stream") return true
13306     (string-equal? %esi "read-from-stream")  # => eax
13307     3d/compare-eax-and 0/imm32/false
13308     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13309     # if (name == "write-to-stream") return true
13310     (string-equal? %esi "write-to-stream")  # => eax
13311     3d/compare-eax-and 0/imm32/false
13312     0f 85/jump-if-!= $has-primitive-name?:end/disp32
13313     # var curr/ecx: (addr primitive) = Primitives
13314     b9/copy-to-ecx Primitives/imm32
13315     {
13316 $has-primitive-name?:loop:
13317       # if (curr == null) break
13318       81 7/subop/compare %ecx 0/imm32
13319       74/jump-if-= break/disp8
13320       # if (primitive->name == name) return true
13321       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
13322 #?       (write-buffered Stderr %eax)
13323 #?       (write-buffered Stderr Newline)
13324 #?       (flush Stderr)
13325       (string-equal? %esi %eax)  # => eax
13326       3d/compare-eax-and 0/imm32/false
13327       75/jump-if-!= $has-primitive-name?:end/disp8
13328 $has-primitive-name?:next-primitive:
13329       # curr = curr->next
13330       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
13331       89/<- %ecx 0/r32/eax
13332       #
13333       e9/jump loop/disp32
13334     }
13335     # return null
13336     b8/copy-to-eax 0/imm32
13337 $has-primitive-name?:end:
13338     # . restore registers
13339     5e/pop-to-esi
13340     59/pop-to-ecx
13341     # . epilogue
13342     89/<- %esp 5/r32/ebp
13343     5d/pop-to-ebp
13344     c3/return
13345 
13346 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13347     # . prologue
13348     55/push-ebp
13349     89/<- %ebp 4/r32/esp
13350     # . save registers
13351     50/push-eax
13352     51/push-ecx
13353     # var op/ecx: (addr array byte) = lookup(stmt->operation)
13354     8b/-> *(ebp+8) 0/r32/eax
13355     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
13356     89/<- %ecx 0/r32/eax
13357     # if (op == "copy") check-mu-copy-stmt
13358     {
13359       (string-equal? %ecx "copy")  # => eax
13360       3d/compare-eax-and 0/imm32/false
13361       74/jump-if-= break/disp8
13362       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13363       e9/jump $check-mu-primitive:end/disp32
13364     }
13365     # if (op == "copy-to") check-mu-copy-to-stmt
13366     {
13367       (string-equal? %ecx "copy-to")  # => eax
13368       3d/compare-eax-and 0/imm32/false
13369       74/jump-if-= break/disp8
13370       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13371       e9/jump $check-mu-primitive:end/disp32
13372     }
13373     # if (op == "compare") check-mu-compare-stmt
13374     {
13375       (string-equal? %ecx "compare")  # => eax
13376       3d/compare-eax-and 0/imm32/false
13377       74/jump-if-= break/disp8
13378       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13379       e9/jump $check-mu-primitive:end/disp32
13380     }
13381     # if (op == "address") check-mu-address-stmt
13382     {
13383       (string-equal? %ecx "address")  # => eax
13384       3d/compare-eax-and 0/imm32/false
13385       74/jump-if-= break/disp8
13386       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13387       e9/jump $check-mu-primitive:end/disp32
13388     }
13389     # if (op == "get") check-mu-get-stmt
13390     {
13391       (string-equal? %ecx "get")  # => eax
13392       3d/compare-eax-and 0/imm32/false
13393       74/jump-if-= break/disp8
13394       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13395       e9/jump $check-mu-primitive:end/disp32
13396     }
13397     # if (op == "index") check-mu-index-stmt
13398     {
13399       (string-equal? %ecx "index")  # => eax
13400       3d/compare-eax-and 0/imm32/false
13401       74/jump-if-= break/disp8
13402       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13403       e9/jump $check-mu-primitive:end/disp32
13404     }
13405     # if (op == "length") check-mu-length-stmt
13406     {
13407       (string-equal? %ecx "length")  # => eax
13408       3d/compare-eax-and 0/imm32/false
13409       74/jump-if-= break/disp8
13410       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13411       e9/jump $check-mu-primitive:end/disp32
13412     }
13413     # if (op == "compute-offset") check-mu-compute-offset-stmt
13414     {
13415       (string-equal? %ecx "compute-offset")  # => eax
13416       3d/compare-eax-and 0/imm32/false
13417       74/jump-if-= break/disp8
13418       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13419       e9/jump $check-mu-primitive:end/disp32
13420     }
13421     # if (op == "copy-object") check-mu-copy-object-stmt
13422     {
13423       (string-equal? %ecx "copy-object")  # => eax
13424       3d/compare-eax-and 0/imm32/false
13425       74/jump-if-= break/disp8
13426       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13427       e9/jump $check-mu-primitive:end/disp32
13428     }
13429     # if (op == "allocate") check-mu-allocate-stmt
13430     {
13431       (string-equal? %ecx "allocate")  # => eax
13432       3d/compare-eax-and 0/imm32/false
13433       74/jump-if-= break/disp8
13434       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13435       e9/jump $check-mu-primitive:end/disp32
13436     }
13437     # if (op == "populate") check-mu-populate-stmt
13438     {
13439       (string-equal? %ecx "populate")  # => eax
13440       3d/compare-eax-and 0/imm32/false
13441       74/jump-if-= break/disp8
13442       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13443       e9/jump $check-mu-primitive:end/disp32
13444     }
13445     # if (op == "populate-stream") check-mu-populate-stream-stmt
13446     {
13447       (string-equal? %ecx "populate-stream")  # => eax
13448       3d/compare-eax-and 0/imm32/false
13449       74/jump-if-= break/disp8
13450       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13451       e9/jump $check-mu-primitive:end/disp32
13452     }
13453     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
13454     {
13455       (string-equal? %ecx "read-from-stream")  # => eax
13456       3d/compare-eax-and 0/imm32/false
13457       74/jump-if-= break/disp8
13458       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13459       e9/jump $check-mu-primitive:end/disp32
13460     }
13461     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
13462     {
13463       (string-equal? %ecx "write-to-stream")  # => eax
13464       3d/compare-eax-and 0/imm32/false
13465       74/jump-if-= break/disp8
13466       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13467       e9/jump $check-mu-primitive:end/disp32
13468     }
13469     # if (op == "convert") check-mu-convert-stmt
13470     {
13471       (string-equal? %ecx "convert")  # => eax
13472       3d/compare-eax-and 0/imm32/false
13473       74/jump-if-= break/disp8
13474       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13475       e9/jump $check-mu-primitive:end/disp32
13476     }
13477     # otherwise check-numberlike-stmt
13478     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13479 $check-mu-primitive:end:
13480     # . restore registers
13481     59/pop-to-ecx
13482     58/pop-to-eax
13483     # . epilogue
13484     89/<- %esp 5/r32/ebp
13485     5d/pop-to-ebp
13486     c3/return
13487 
13488 # by default, Mu primitives should only operate on 'number-like' types
13489 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13490     # . prologue
13491     55/push-ebp
13492     89/<- %ebp 4/r32/esp
13493     # . save registers
13494     50/push-eax
13495     51/push-ecx
13496     56/push-esi
13497     # esi = stmt
13498     8b/-> *(ebp+8) 6/r32/esi
13499     # var gas/ecx: int = 2
13500     b9/copy-to-ecx 2/imm32
13501     # - check at most 1 output
13502     # var output/eax: (addr stmt-var) = stmt->outputs
13503     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
13504     {
13505       3d/compare-eax-and 0/imm32
13506       74/jump-if-= break/disp8
13507 $check-mu-numberlike-primitive:output:
13508       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13509       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
13510       3d/compare-eax-and 0/imm32
13511       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
13512       # check output is in a register
13513       # --gas
13514       49/decrement-ecx
13515     }
13516     # - check first inout
13517     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13518     {
13519       3d/compare-eax-and 0/imm32
13520       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
13521 $check-mu-numberlike-primitive:first-inout:
13522       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13523       # --gas
13524       49/decrement-ecx
13525     }
13526     # - check second inout
13527     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
13528     {
13529       3d/compare-eax-and 0/imm32
13530       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
13531 $check-mu-numberlike-primitive:second-inout:
13532       # is a second inout allowed?
13533       81 7/subop/compare %ecx 0/imm32
13534       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
13535 $check-mu-numberlike-primitive:second-inout-permitted:
13536       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
13537     }
13538 $check-mu-numberlike-primitive:third-inout:
13539     # if there's a third arg, raise an error
13540     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
13541     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
13542 $check-mu-numberlike-primitive:end:
13543     # . restore registers
13544     5e/pop-to-esi
13545     59/pop-to-ecx
13546     58/pop-to-eax
13547     # . epilogue
13548     89/<- %esp 5/r32/ebp
13549     5d/pop-to-ebp
13550     c3/return
13551 
13552 $check-mu-numberlike-primitive:error-too-many-inouts:
13553     (write-buffered *(ebp+0x10) "fn ")
13554     8b/-> *(ebp+0xc) 0/r32/eax
13555     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13556     (write-buffered *(ebp+0x10) %eax)
13557     (write-buffered *(ebp+0x10) ": stmt ")
13558     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
13559     (write-buffered *(ebp+0x10) %eax)
13560     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
13561     (flush *(ebp+0x10))
13562     (stop *(ebp+0x14) 1)
13563     # never gets here
13564 
13565 $check-mu-numberlike-primitive:error-too-many-outputs:
13566     (write-buffered *(ebp+0x10) "fn ")
13567     8b/-> *(ebp+0xc) 0/r32/eax
13568     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13569     (write-buffered *(ebp+0x10) %eax)
13570     (write-buffered *(ebp+0x10) ": stmt ")
13571     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
13572     (write-buffered *(ebp+0x10) %eax)
13573     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
13574     (flush *(ebp+0x10))
13575     (stop *(ebp+0x14) 1)
13576     # never gets here
13577 
13578 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13579     # . prologue
13580     55/push-ebp
13581     89/<- %ebp 4/r32/esp
13582     # . save registers
13583     50/push-eax
13584     56/push-esi
13585     # var t/esi: (addr type-tree) = lookup(v->value->type)
13586     8b/-> *(ebp+8) 0/r32/eax
13587     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13588     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
13589     89/<- %esi 0/r32/eax
13590 $check-mu-numberlike-arg:check-literal:
13591     # if t is an int, return
13592     (is-simple-mu-type? %esi 0)  # literal => eax
13593     3d/compare-eax-and 0/imm32/false
13594     75/jump-if-!= $check-mu-numberlike-arg:end/disp8
13595 $check-mu-numberlike-arg:check-addr:
13596     # if t is an addr and v is dereferenced, return
13597     {
13598       (is-mu-addr-type? %esi)  # => eax
13599       3d/compare-eax-and 0/imm32/false
13600       74/jump-if-= break/disp8
13601       8b/-> *(ebp+8) 0/r32/eax
13602       8b/-> *(eax+0x10) 0/r32/eax
13603       3d/compare-eax-and 0/imm32/false
13604       75/jump-if-!= $check-mu-numberlike-arg:end/disp8
13605     }
13606 $check-mu-numberlike-arg:output-checks:
13607     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
13608 $check-mu-numberlike-arg:end:
13609     # . restore registers
13610     5e/pop-to-esi
13611     58/pop-to-eax
13612     # . epilogue
13613     89/<- %esp 5/r32/ebp
13614     5d/pop-to-ebp
13615     c3/return
13616 
13617 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13618     # . prologue
13619     55/push-ebp
13620     89/<- %ebp 4/r32/esp
13621     # . save registers
13622     50/push-eax
13623     56/push-esi
13624     # var t/esi: (addr type-tree) = lookup(v->value->type)
13625     8b/-> *(ebp+8) 0/r32/eax
13626     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13627     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
13628     89/<- %esi 0/r32/eax
13629 $check-mu-numberlike-output:check-int:
13630     # if t is an int, return
13631     (is-simple-mu-type? %esi 1)  # int => eax
13632     3d/compare-eax-and 0/imm32/false
13633     0f 85/jump-if-!= $check-mu-numberlike-output:end/disp32
13634 $check-mu-numberlike-output:check-float:
13635     # if t is a float, return
13636     (is-simple-mu-type? %esi 0xf)  # float => eax
13637     3d/compare-eax-and 0/imm32/false
13638     75/jump-if-!= $check-mu-numberlike-output:end/disp8
13639 $check-mu-numberlike-output:check-boolean:
13640     # if t is a boolean, return
13641     (is-simple-mu-type? %esi 5)  # boolean => eax
13642     3d/compare-eax-and 0/imm32/false
13643     75/jump-if-!= $check-mu-numberlike-output:end/disp8
13644 $check-mu-numberlike-output:check-byte:
13645     # if t is a byte, return
13646     (is-simple-mu-type? %esi 8)  # byte => eax
13647     3d/compare-eax-and 0/imm32/false
13648     75/jump-if-!= $check-mu-numberlike-output:end/disp8
13649 $check-mu-numberlike-output:check-code-point:
13650     # if t is a code-point, return
13651     (is-simple-mu-type? %esi 0xd)  # code-point => eax
13652     3d/compare-eax-and 0/imm32/false
13653     75/jump-if-!= $check-mu-numberlike-output:end/disp8
13654 $check-mu-numberlike-output:check-grapheme:
13655     # if t is a grapheme, return
13656     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
13657     3d/compare-eax-and 0/imm32/false
13658     75/jump-if-!= $check-mu-numberlike-output:end/disp8
13659     e9/jump $check-mu-numberlike-output:fail/disp32
13660 $check-mu-numberlike-output:end:
13661     # . restore registers
13662     5e/pop-to-esi
13663     58/pop-to-eax
13664     # . epilogue
13665     89/<- %esp 5/r32/ebp
13666     5d/pop-to-ebp
13667     c3/return
13668 
13669 $check-mu-numberlike-output:fail:
13670     # otherwise raise an error
13671     (write-buffered *(ebp+0x14) "fn ")
13672     8b/-> *(ebp+0x10) 0/r32/eax
13673     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13674     (write-buffered *(ebp+0x14) %eax)
13675     (write-buffered *(ebp+0x14) ": stmt ")
13676     8b/-> *(ebp+0xc) 0/r32/eax
13677     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
13678     (write-buffered *(ebp+0x14) %eax)
13679     (write-buffered *(ebp+0x14) ": only non-addr scalar args permitted\n")
13680     (flush *(ebp+0x14))
13681     (stop *(ebp+0x18) 1)
13682     # never gets here
13683 
13684 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13685     # . prologue
13686     55/push-ebp
13687     89/<- %ebp 4/r32/esp
13688     # . save registers
13689 $check-mu-copy-stmt:end:
13690     # . restore registers
13691     # . epilogue
13692     89/<- %esp 5/r32/ebp
13693     5d/pop-to-ebp
13694     c3/return
13695 
13696 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13697     # . prologue
13698     55/push-ebp
13699     89/<- %ebp 4/r32/esp
13700     # . save registers
13701 $check-mu-copy-to-stmt:end:
13702     # . restore registers
13703     # . epilogue
13704     89/<- %esp 5/r32/ebp
13705     5d/pop-to-ebp
13706     c3/return
13707 
13708 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13709     # . prologue
13710     55/push-ebp
13711     89/<- %ebp 4/r32/esp
13712     # . save registers
13713 $check-mu-compare-stmt:end:
13714     # . restore registers
13715     # . epilogue
13716     89/<- %esp 5/r32/ebp
13717     5d/pop-to-ebp
13718     c3/return
13719 
13720 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13721     # . prologue
13722     55/push-ebp
13723     89/<- %ebp 4/r32/esp
13724     # . save registers
13725 $check-mu-address-stmt:end:
13726     # . restore registers
13727     # . epilogue
13728     89/<- %esp 5/r32/ebp
13729     5d/pop-to-ebp
13730     c3/return
13731 
13732 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
13733     # . prologue
13734     55/push-ebp
13735     89/<- %ebp 4/r32/esp
13736     # . save registers
13737     50/push-eax
13738     51/push-ecx
13739     52/push-edx
13740     53/push-ebx
13741     56/push-esi
13742     57/push-edi
13743     # esi = stmt
13744     8b/-> *(ebp+8) 6/r32/esi
13745     # - check for 0 inouts
13746     # var base/ecx: (addr var) = stmt->inouts->value
13747     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13748     3d/compare-eax-and 0/imm32/false
13749     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
13750     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13751     89/<- %ecx 0/r32/eax
13752 $check-mu-get-stmt:check-base:
13753     # - check base type
13754     # if it's an 'addr', check that it's in a register
13755     # var base-type/ebx: (addr type-tree) = lookup(base->type)
13756     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
13757     89/<- %ebx 0/r32/eax
13758     {
13759       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
13760       0f 85/jump-if-!= break/disp32
13761 $check-mu-get-stmt:base-is-compound:
13762       # if (type->left != addr) break
13763       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
13764       (is-simple-mu-type? %eax 2)  # addr => eax
13765       3d/compare-eax-and 0/imm32/false
13766       74/jump-if-= break/disp8
13767 $check-mu-get-stmt:base-is-addr:
13768       # now check for register
13769       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
13770       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
13771 $check-mu-get-stmt:base-is-addr-in-register:
13772       # type->left is now an addr; skip it
13773       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
13774       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
13775       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
13776 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
13777       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
13778       89/<- %ebx 0/r32/eax
13779     }
13780 $check-mu-get-stmt:check-base-typeinfo:
13781     # ensure type is a container
13782     # var base-type-id/ebx: type-id = base-type->value
13783     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
13784     (is-container? %ebx)  # => eax
13785     3d/compare-eax-and 0/imm32/false
13786     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
13787     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
13788     # . var container/ecx: (handle typeinfo)
13789     68/push 0/imm32
13790     68/push 0/imm32
13791     89/<- %ecx 4/r32/esp
13792     # .
13793     (find-typeinfo %ebx %ecx)
13794     (lookup *ecx *(ecx+4))  # => eax
13795     # . reclaim container
13796     81 0/subop/add %esp 8/imm32
13797     # .
13798     89/<- %edx 0/r32/eax
13799     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
13800     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13801     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
13802     89/<- %ecx 0/r32/eax
13803     # - check for 1 inout
13804     3d/compare-eax-and 0/imm32/false
13805     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
13806     # var offset/ecx: (addr var) = lookup(offset->value)
13807     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
13808     89/<- %ecx 0/r32/eax
13809     # - check for valid field
13810     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
13811     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
13812     # - check for too many inouts
13813     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13814     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
13815     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
13816     3d/compare-eax-and 0/imm32/false
13817     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
13818     # var output/edi: (addr var) = stmt->outputs->value
13819     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
13820     # - check for 0 outputs
13821     3d/compare-eax-and 0/imm32/false
13822     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
13823     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13824     89/<- %edi 0/r32/eax
13825 $check-mu-get-stmt:check-output-type:
13826     # - check output type
13827     # must be in register
13828     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
13829     3d/compare-eax-and 0/imm32
13830     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
13831     # must have a non-atomic type
13832     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
13833     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
13834     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
13835     # type must start with (addr ...)
13836     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
13837     (is-simple-mu-type? %eax 2)  # => eax
13838     3d/compare-eax-and 0/imm32/false
13839     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
13840 $check-mu-get-stmt:check-output-type-match:
13841     # payload of addr type must match 'type' definition
13842     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
13843     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
13844     # if (payload->right == null) payload = payload->left
13845     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
13846     {
13847       75/jump-if-!= break/disp8
13848       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
13849     }
13850     89/<- %edi 0/r32/eax
13851     # . var output-name/ecx: (addr array byte)
13852     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
13853     89/<- %ecx 0/r32/eax
13854     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
13855     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
13856     (get %eax %ecx 0x10)  # => eax
13857     # .
13858     (lookup *eax *(eax+4))  # => eax
13859     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
13860     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
13861     # .
13862     (type-equal? %edi %eax)  # => eax
13863     3d/compare-eax-and 0/imm32/false
13864     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
13865     # - check for too many outputs
13866     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
13867     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
13868     3d/compare-eax-and 0/imm32/false
13869     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
13870 $check-mu-get-stmt:end:
13871     # . restore registers
13872     5f/pop-to-edi
13873     5e/pop-to-esi
13874     5b/pop-to-ebx
13875     5a/pop-to-edx
13876     59/pop-to-ecx
13877     58/pop-to-eax
13878     # . epilogue
13879     89/<- %esp 5/r32/ebp
13880     5d/pop-to-ebp
13881     c3/return
13882 
13883 $check-mu-get-stmt:error-too-few-inouts:
13884     (write-buffered *(ebp+0x10) "fn ")
13885     8b/-> *(ebp+0xc) 0/r32/eax
13886     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13887     (write-buffered *(ebp+0x10) %eax)
13888     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
13889     (flush *(ebp+0x10))
13890     (stop *(ebp+0x14) 1)
13891     # never gets here
13892 
13893 $check-mu-get-stmt:error-too-many-inouts:
13894     (write-buffered *(ebp+0x10) "fn ")
13895     8b/-> *(ebp+0xc) 0/r32/eax
13896     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13897     (write-buffered *(ebp+0x10) %eax)
13898     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
13899     (flush *(ebp+0x10))
13900     (stop *(ebp+0x14) 1)
13901     # never gets here
13902 
13903 $check-mu-get-stmt:error-too-few-outputs:
13904     (write-buffered *(ebp+0x10) "fn ")
13905     8b/-> *(ebp+0xc) 0/r32/eax
13906     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13907     (write-buffered *(ebp+0x10) %eax)
13908     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
13909     (flush *(ebp+0x10))
13910     (stop *(ebp+0x14) 1)
13911     # never gets here
13912 
13913 $check-mu-get-stmt:error-too-many-outputs:
13914     (write-buffered *(ebp+0x10) "fn ")
13915     8b/-> *(ebp+0xc) 0/r32/eax
13916     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13917     (write-buffered *(ebp+0x10) %eax)
13918     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
13919     (flush *(ebp+0x10))
13920     (stop *(ebp+0x14) 1)
13921     # never gets here
13922 
13923 $check-mu-get-stmt:error-bad-base:
13924     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
13925     (write-buffered *(ebp+0x10) "fn ")
13926     8b/-> *(ebp+0xc) 0/r32/eax
13927     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13928     (write-buffered *(ebp+0x10) %eax)
13929     (write-buffered *(ebp+0x10) ": stmt get: var '")
13930     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13931     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13932     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13933     (write-buffered *(ebp+0x10) %eax)
13934     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
13935     (flush *(ebp+0x10))
13936     (stop *(ebp+0x14) 1)
13937     # never gets here
13938 
13939 $check-mu-get-stmt:error-base-type-addr-but-not-register:
13940     (write-buffered *(ebp+0x10) "fn ")
13941     8b/-> *(ebp+0xc) 0/r32/eax
13942     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13943     (write-buffered *(ebp+0x10) %eax)
13944     (write-buffered *(ebp+0x10) ": stmt get: var '")
13945     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
13946     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
13947     (lookup *eax *(eax+4))  # Var-name Var-name => eax
13948     (write-buffered *(ebp+0x10) %eax)
13949     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
13950     (flush *(ebp+0x10))
13951     (stop *(ebp+0x14) 1)
13952     # never gets here
13953 
13954 $check-mu-get-stmt:error-bad-field:
13955     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
13956     (write-buffered *(ebp+0x10) "fn ")
13957     8b/-> *(ebp+0xc) 0/r32/eax
13958     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13959     (write-buffered *(ebp+0x10) %eax)
13960     (write-buffered *(ebp+0x10) ": stmt get: type '")
13961     # . write(Type-id->data[tmp])
13962     bf/copy-to-edi Type-id/imm32
13963     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
13964     # .
13965     (write-buffered *(ebp+0x10) "' has no member called '")
13966     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
13967     (write-buffered *(ebp+0x10) %eax)
13968     (write-buffered *(ebp+0x10) "'\n")
13969     (flush *(ebp+0x10))
13970     (stop *(ebp+0x14) 1)
13971     # never gets here
13972 
13973 $check-mu-get-stmt:error-output-not-in-register:
13974     (write-buffered *(ebp+0x10) "fn ")
13975     8b/-> *(ebp+0xc) 0/r32/eax
13976     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13977     (write-buffered *(ebp+0x10) %eax)
13978     (write-buffered *(ebp+0x10) ": stmt get: output '")
13979     (lookup *edi *(edi+4))  # Var-name Var-name => eax
13980     (write-buffered *(ebp+0x10) %eax)
13981     (write-buffered *(ebp+0x10) "' is not in a register\n")
13982     (flush *(ebp+0x10))
13983     (stop *(ebp+0x14) 1)
13984     # never gets here
13985 
13986 $check-mu-get-stmt:error-output-type-not-address:
13987     (write-buffered *(ebp+0x10) "fn ")
13988     8b/-> *(ebp+0xc) 0/r32/eax
13989     (lookup *eax *(eax+4))  # Function-name Function-name => eax
13990     (write-buffered *(ebp+0x10) %eax)
13991     (write-buffered *(ebp+0x10) ": stmt get: output must be an address\n")
13992     (flush *(ebp+0x10))
13993     (stop *(ebp+0x14) 1)
13994     # never gets here
13995 
13996 $check-mu-get-stmt:error-bad-output-type:
13997     (write-buffered *(ebp+0x10) "fn ")
13998     8b/-> *(ebp+0xc) 0/r32/eax
13999     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14000     (write-buffered *(ebp+0x10) %eax)
14001     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
14002     (write-buffered *(ebp+0x10) %ecx)
14003     (write-buffered *(ebp+0x10) "' of type '")
14004     bf/copy-to-edi Type-id/imm32
14005     (write-buffered *(ebp+0x10) *(edi+ebx<<2+0xc))
14006     (write-buffered *(ebp+0x10) "'\n")
14007     (flush *(ebp+0x10))
14008     (stop *(ebp+0x14) 1)
14009     # never gets here
14010 
14011 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14012     # . prologue
14013     55/push-ebp
14014     89/<- %ebp 4/r32/esp
14015     # . save registers
14016     50/push-eax
14017     51/push-ecx
14018     52/push-edx
14019     53/push-ebx
14020     56/push-esi
14021     57/push-edi
14022     # esi = stmt
14023     8b/-> *(ebp+8) 6/r32/esi
14024     # - check for 0 inouts
14025     # var base/ecx: (addr var) = stmt->inouts->value
14026     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14027 $check-mu-index-stmt:check-no-inouts:
14028     3d/compare-eax-and 0/imm32
14029     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
14030     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14031     89/<- %ecx 0/r32/eax
14032     # - check base type is either (addr array ...) in register or (array ...) on stack
14033     # var base-type/ebx: (addr type-tree) = lookup(base->type)
14034     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14035     89/<- %ebx 0/r32/eax
14036     # if base-type is an atom, abort with a precise error
14037     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
14038     {
14039       74/jump-if-= break/disp8
14040       (is-simple-mu-type? %ebx 3)  # array => eax
14041       3d/compare-eax-and 0/imm32/false
14042       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
14043       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
14044     }
14045 $check-mu-index-stmt:base-is-compound:
14046     # if type->left not addr or array, abort
14047     {
14048       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
14049       (is-simple-mu-type? %eax 2)  # addr => eax
14050       3d/compare-eax-and 0/imm32/false
14051       75/jump-if-!= break/disp8
14052       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
14053       (is-simple-mu-type? %eax 3)  # array => eax
14054       3d/compare-eax-and 0/imm32/false
14055       75/jump-if-!= break/disp8
14056       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
14057     }
14058     # if (type->left == addr) ensure type->right->left == array and type->register exists
14059     {
14060       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
14061       (is-simple-mu-type? %eax 2)  # addr => eax
14062       3d/compare-eax-and 0/imm32/false
14063       74/jump-if-= break/disp8
14064 $check-mu-index-stmt:base-is-addr:
14065       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
14066       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
14067       (is-simple-mu-type? %eax 3)  # array => eax
14068       3d/compare-eax-and 0/imm32/false
14069       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
14070 $check-mu-index-stmt:check-base-addr-is-register:
14071       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
14072       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
14073     }
14074     # if (type->left == array) ensure type->register doesn't exist
14075     {
14076       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
14077       (is-simple-mu-type? %eax 3)  # array => eax
14078       3d/compare-eax-and 0/imm32/false
14079       74/jump-if-= break/disp8
14080 $check-mu-index-stmt:base-is-array:
14081       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
14082       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
14083     }
14084     # if (base-type->left == addr) base-type = base-type->right
14085     {
14086       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
14087       (is-simple-mu-type? %eax 2)  # addr => eax
14088       3d/compare-eax-and 0/imm32/false
14089       74/jump-if-= break/disp8
14090       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
14091       89/<- %ebx 0/r32/eax
14092     }
14093     # - check for 1 inout
14094     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
14095     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14096     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
14097 $check-mu-index-stmt:check-single-inout:
14098     3d/compare-eax-and 0/imm32
14099     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
14100     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14101     89/<- %ecx 0/r32/eax
14102     # - check index is either a literal or register
14103     # var index-type/edx: (addr type-tree)
14104     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14105     89/<- %edx 0/r32/eax
14106     # if index type is an atom, it must be a literal or int
14107     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
14108     {
14109       74/jump-if-= break/disp8
14110 $check-mu-index-stmt:index-type-is-atom:
14111       (is-simple-mu-type? %edx 0)  # literal => eax
14112       3d/compare-eax-and 0/imm32/false
14113       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
14114       (is-simple-mu-type? %edx 1)  # int => eax
14115       3d/compare-eax-and 0/imm32/false
14116       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
14117       (is-simple-mu-type? %edx 7)  # offset => eax
14118       3d/compare-eax-and 0/imm32/false
14119       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
14120       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
14121     }
14122     # if index type is a non-atom: it must be an offset
14123     {
14124       75/jump-if-!= break/disp8
14125 $check-mu-index-stmt:index-type-is-non-atom:
14126       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
14127       (is-simple-mu-type? %eax 7)  # offset => eax
14128       3d/compare-eax-and 0/imm32/false
14129       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
14130     }
14131 $check-mu-index-stmt:index-type-done:
14132     # check index is either a literal or in a register
14133     {
14134       (is-simple-mu-type? %edx 0)  # literal => eax
14135       3d/compare-eax-and 0/imm32/false
14136       75/jump-if-!= break/disp8
14137 $check-mu-index-stmt:check-index-in-register:
14138       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
14139       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
14140     }
14141     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
14142     {
14143       (is-simple-mu-type? %edx 1)  # int => eax
14144       3d/compare-eax-and 0/imm32/false
14145       74/jump-if-= break/disp8
14146 $check-mu-index-stmt:check-index-can-be-int:
14147       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14148       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14149       (array-element-size %eax)  # => eax
14150       3d/compare-eax-and 1/imm32
14151       74/jump-if-= break/disp8
14152       3d/compare-eax-and 2/imm32
14153       74/jump-if-= break/disp8
14154       3d/compare-eax-and 4/imm32
14155       74/jump-if-= break/disp8
14156       3d/compare-eax-and 8/imm32
14157       74/jump-if-= break/disp8
14158       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
14159     }
14160     # - check for too many inouts
14161     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14162     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
14163     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
14164     3d/compare-eax-and 0/imm32/false
14165     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
14166     # - check for 0 outputs
14167     # var output/edi: (addr var) = stmt->outputs->value
14168     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
14169     3d/compare-eax-and 0/imm32/false
14170     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
14171     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14172     89/<- %edi 0/r32/eax
14173     # - check output type
14174     # must have a non-atomic type
14175     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
14176     89/<- %edx 0/r32/eax
14177     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
14178     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
14179     # type must start with (addr ...)
14180     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
14181     (is-simple-mu-type? %eax 2)  # addr => eax
14182     3d/compare-eax-and 0/imm32/false
14183     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
14184     # if tail(base-type) != tail(output-type) abort
14185     (type-tail %ebx)  # => eax
14186     89/<- %ebx 0/r32/eax
14187     (type-tail %edx)  # => eax
14188     (type-equal? %ebx %eax)  # => eax
14189     3d/compare-eax-and 0/imm32/false
14190     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
14191     # - check for too many outputs
14192     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
14193     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
14194     3d/compare-eax-and 0/imm32/false
14195     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
14196 $check-mu-index-stmt:end:
14197     # . restore registers
14198     5f/pop-to-edi
14199     5e/pop-to-esi
14200     5b/pop-to-ebx
14201     5a/pop-to-edx
14202     59/pop-to-ecx
14203     58/pop-to-eax
14204     # . epilogue
14205     89/<- %esp 5/r32/ebp
14206     5d/pop-to-ebp
14207     c3/return
14208 
14209 $check-mu-index-stmt:error-base-non-array-type:
14210     (write-buffered *(ebp+0x10) "fn ")
14211     8b/-> *(ebp+0xc) 0/r32/eax
14212     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14213     (write-buffered *(ebp+0x10) %eax)
14214     (write-buffered *(ebp+0x10) ": stmt index: var '")
14215     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14216     (write-buffered *(ebp+0x10) %eax)
14217     (write-buffered *(ebp+0x10) "' is not an array\n")
14218     (flush *(ebp+0x10))
14219     (stop *(ebp+0x14) 1)
14220     # never gets here
14221 
14222 $check-mu-index-stmt:error-base-array-atom-type:
14223     (write-buffered *(ebp+0x10) "fn ")
14224     8b/-> *(ebp+0xc) 0/r32/eax
14225     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14226     (write-buffered *(ebp+0x10) %eax)
14227     (write-buffered *(ebp+0x10) ": stmt index: array '")
14228     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14229     (write-buffered *(ebp+0x10) %eax)
14230     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
14231     (flush *(ebp+0x10))
14232     (stop *(ebp+0x14) 1)
14233     # never gets here
14234 
14235 $check-mu-index-stmt:error-base-address-array-type-on-stack:
14236     (write-buffered *(ebp+0x10) "fn ")
14237     8b/-> *(ebp+0xc) 0/r32/eax
14238     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14239     (write-buffered *(ebp+0x10) %eax)
14240     (write-buffered *(ebp+0x10) ": stmt index: var '")
14241     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14242     (write-buffered *(ebp+0x10) %eax)
14243     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
14244     (flush *(ebp+0x10))
14245     (stop *(ebp+0x14) 1)
14246     # never gets here
14247 
14248 $check-mu-index-stmt:error-base-array-type-in-register:
14249     (write-buffered *(ebp+0x10) "fn ")
14250     8b/-> *(ebp+0xc) 0/r32/eax
14251     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14252     (write-buffered *(ebp+0x10) %eax)
14253     (write-buffered *(ebp+0x10) ": stmt index: var '")
14254     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14255     (write-buffered *(ebp+0x10) %eax)
14256     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
14257     (flush *(ebp+0x10))
14258     (stop *(ebp+0x14) 1)
14259     # never gets here
14260 
14261 $check-mu-index-stmt:error-too-few-inouts:
14262     (write-buffered *(ebp+0x10) "fn ")
14263     8b/-> *(ebp+0xc) 0/r32/eax
14264     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14265     (write-buffered *(ebp+0x10) %eax)
14266     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
14267     (flush *(ebp+0x10))
14268     (stop *(ebp+0x14) 1)
14269     # never gets here
14270 
14271 $check-mu-index-stmt:error-invalid-index-type:
14272     (write-buffered *(ebp+0x10) "fn ")
14273     8b/-> *(ebp+0xc) 0/r32/eax
14274     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14275     (write-buffered *(ebp+0x10) %eax)
14276     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
14277     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14278     (write-buffered *(ebp+0x10) %eax)
14279     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
14280     (flush *(ebp+0x10))
14281     (stop *(ebp+0x14) 1)
14282     # never gets here
14283 
14284 $check-mu-index-stmt:error-index-offset-atom-type:
14285     (write-buffered *(ebp+0x10) "fn ")
14286     8b/-> *(ebp+0xc) 0/r32/eax
14287     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14288     (write-buffered *(ebp+0x10) %eax)
14289     (write-buffered *(ebp+0x10) ": stmt index: offset '")
14290     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14291     (write-buffered *(ebp+0x10) %eax)
14292     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
14293     (flush *(ebp+0x10))
14294     (stop *(ebp+0x14) 1)
14295     # never gets here
14296 
14297 $check-mu-index-stmt:error-index-on-stack:
14298     (write-buffered *(ebp+0x10) "fn ")
14299     8b/-> *(ebp+0xc) 0/r32/eax
14300     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14301     (write-buffered *(ebp+0x10) %eax)
14302     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
14303     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
14304     (write-buffered *(ebp+0x10) %eax)
14305     (write-buffered *(ebp+0x10) "' must be in a register\n")
14306     (flush *(ebp+0x10))
14307     (stop *(ebp+0x14) 1)
14308     # never gets here
14309 
14310 $check-mu-index-stmt:error-index-needs-offset:
14311     (write-buffered *(ebp+0x10) "fn ")
14312     8b/-> *(ebp+0xc) 0/r32/eax
14313     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14314     (write-buffered *(ebp+0x10) %eax)
14315     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
14316     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14317     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
14318     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14319     (write-buffered *(ebp+0x10) %eax)
14320     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
14321     (flush *(ebp+0x10))
14322     (stop *(ebp+0x14) 1)
14323     # never gets here
14324 
14325 $check-mu-index-stmt:error-too-many-inouts:
14326     (write-buffered *(ebp+0x10) "fn ")
14327     8b/-> *(ebp+0xc) 0/r32/eax
14328     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14329     (write-buffered *(ebp+0x10) %eax)
14330     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
14331     (flush *(ebp+0x10))
14332     (stop *(ebp+0x14) 1)
14333     # never gets here
14334 
14335 $check-mu-index-stmt:error-too-few-outputs:
14336     (write-buffered *(ebp+0x10) "fn ")
14337     8b/-> *(ebp+0xc) 0/r32/eax
14338     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14339     (write-buffered *(ebp+0x10) %eax)
14340     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
14341     (flush *(ebp+0x10))
14342     (stop *(ebp+0x14) 1)
14343     # never gets here
14344 
14345 $check-mu-index-stmt:error-too-many-outputs:
14346     (write-buffered *(ebp+0x10) "fn ")
14347     8b/-> *(ebp+0xc) 0/r32/eax
14348     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14349     (write-buffered *(ebp+0x10) %eax)
14350     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
14351     (flush *(ebp+0x10))
14352     (stop *(ebp+0x14) 1)
14353     # never gets here
14354 
14355 $check-mu-index-stmt:error-output-not-in-register:
14356     (write-buffered *(ebp+0x10) "fn ")
14357     8b/-> *(ebp+0xc) 0/r32/eax
14358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14359     (write-buffered *(ebp+0x10) %eax)
14360     (write-buffered *(ebp+0x10) ": stmt index: output '")
14361     (lookup *edi *(edi+4))  # Var-name Var-name => eax
14362     (write-buffered *(ebp+0x10) %eax)
14363     (write-buffered *(ebp+0x10) "' is not in a register\n")
14364     (flush *(ebp+0x10))
14365     (stop *(ebp+0x14) 1)
14366     # never gets here
14367 
14368 $check-mu-index-stmt:error-output-type-not-address:
14369     (write-buffered *(ebp+0x10) "fn ")
14370     8b/-> *(ebp+0xc) 0/r32/eax
14371     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14372     (write-buffered *(ebp+0x10) %eax)
14373     (write-buffered *(ebp+0x10) ": stmt index: output '")
14374     (lookup *edi *(edi+4))  # Var-name Var-name => eax
14375     (write-buffered *(ebp+0x10) %eax)
14376     (write-buffered *(ebp+0x10) "' must be an address\n")
14377     (flush *(ebp+0x10))
14378     (stop *(ebp+0x14) 1)
14379     # never gets here
14380 
14381 $check-mu-index-stmt:error-bad-output-type:
14382     (write-buffered *(ebp+0x10) "fn ")
14383     8b/-> *(ebp+0xc) 0/r32/eax
14384     (lookup *eax *(eax+4))  # Function-name Function-name => eax
14385     (write-buffered *(ebp+0x10) %eax)
14386     (write-buffered *(ebp+0x10) ": stmt index: output '")
14387     (lookup *edi *(edi+4))  # Var-name Var-name => eax
14388     (write-buffered *(ebp+0x10) %eax)
14389     (write-buffered *(ebp+0x10) "' does not have the right type\n")
14390     (flush *(ebp+0x10))
14391     (stop *(ebp+0x14) 1)
14392     # never gets here
14393 
14394 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14395     # . prologue
14396     55/push-ebp
14397     89/<- %ebp 4/r32/esp
14398     # . save registers
14399 $check-mu-length-stmt:end:
14400     # . restore registers
14401     # . epilogue
14402     89/<- %esp 5/r32/ebp
14403     5d/pop-to-ebp
14404     c3/return
14405 
14406 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14407     # . prologue
14408     55/push-ebp
14409     89/<- %ebp 4/r32/esp
14410     # . save registers
14411 $check-mu-compute-offset-stmt:end:
14412     # . restore registers
14413     # . epilogue
14414     89/<- %esp 5/r32/ebp
14415     5d/pop-to-ebp
14416     c3/return
14417 
14418 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14419     # . prologue
14420     55/push-ebp
14421     89/<- %ebp 4/r32/esp
14422     # . save registers
14423 $check-mu-copy-object-stmt:end:
14424     # . restore registers
14425     # . epilogue
14426     89/<- %esp 5/r32/ebp
14427     5d/pop-to-ebp
14428     c3/return
14429 
14430 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14431     # . prologue
14432     55/push-ebp
14433     89/<- %ebp 4/r32/esp
14434     # . save registers
14435 $check-mu-allocate-stmt:end:
14436     # . restore registers
14437     # . epilogue
14438     89/<- %esp 5/r32/ebp
14439     5d/pop-to-ebp
14440     c3/return
14441 
14442 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14443     # . prologue
14444     55/push-ebp
14445     89/<- %ebp 4/r32/esp
14446     # . save registers
14447 $check-mu-populate-stmt:end:
14448     # . restore registers
14449     # . epilogue
14450     89/<- %esp 5/r32/ebp
14451     5d/pop-to-ebp
14452     c3/return
14453 
14454 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14455     # . prologue
14456     55/push-ebp
14457     89/<- %ebp 4/r32/esp
14458     # . save registers
14459 $check-mu-populate-stream-stmt:end:
14460     # . restore registers
14461     # . epilogue
14462     89/<- %esp 5/r32/ebp
14463     5d/pop-to-ebp
14464     c3/return
14465 
14466 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14467     # . prologue
14468     55/push-ebp
14469     89/<- %ebp 4/r32/esp
14470     # . save registers
14471 $check-mu-read-from-stream-stmt:end:
14472     # . restore registers
14473     # . epilogue
14474     89/<- %esp 5/r32/ebp
14475     5d/pop-to-ebp
14476     c3/return
14477 
14478 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14479     # . prologue
14480     55/push-ebp
14481     89/<- %ebp 4/r32/esp
14482     # . save registers
14483 $check-mu-write-to-stream-stmt:end:
14484     # . restore registers
14485     # . epilogue
14486     89/<- %esp 5/r32/ebp
14487     5d/pop-to-ebp
14488     c3/return
14489 
14490 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14491     # . prologue
14492     55/push-ebp
14493     89/<- %ebp 4/r32/esp
14494     # . save registers
14495 $check-mu-convert-stmt:end:
14496     # . restore registers
14497     # . epilogue
14498     89/<- %esp 5/r32/ebp
14499     5d/pop-to-ebp
14500     c3/return
14501 
14502 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14503     # . prologue
14504     55/push-ebp
14505     89/<- %ebp 4/r32/esp
14506     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
14507     68/push 0/imm32
14508     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
14509     81 5/subop/subtract %esp 0x60/imm32
14510     68/push 0x60/imm32/size
14511     68/push 0/imm32/read
14512     68/push 0/imm32/write
14513     # save a pointer to type-parameters-storage at type-parameters
14514     89/<- *(ebp-4) 4/r32/esp
14515     (clear-stream *(ebp-4))
14516     # . save registers
14517     50/push-eax
14518     51/push-ecx
14519     52/push-edx
14520     53/push-ebx
14521     56/push-esi
14522     57/push-edi
14523     # esi = stmt
14524     8b/-> *(ebp+8) 6/r32/esi
14525     # edi = callee
14526     8b/-> *(ebp+0xc) 7/r32/edi
14527     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
14528     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
14529     89/<- %ecx 0/r32/eax
14530     # var expected/edx: (addr list var) = lookup(f->inouts)
14531     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
14532     89/<- %edx 0/r32/eax
14533     {
14534 $check-mu-call:check-for-inouts:
14535       # if (inouts == 0) break
14536       81 7/subop/compare %ecx 0/imm32
14537       0f 84/jump-if-= break/disp32
14538       # if (expected == 0) error
14539       81 7/subop/compare %edx 0/imm32
14540       0f 84/jump-if-= break/disp32
14541 $check-mu-call:check-inout-type:
14542       # var v/eax: (addr v) = lookup(inouts->value)
14543       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14544       # var t/ebx: (addr type-tree) = lookup(v->type)
14545       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14546       89/<- %ebx 0/r32/eax
14547       # if (inouts->is-deref?) t = t->right  # TODO: check that t->left is an addr
14548       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
14549       {
14550         74/jump-if-= break/disp8
14551         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
14552         89/<- %ebx 0/r32/eax
14553         # if t->right is null, t = t->left
14554         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
14555         75/jump-if-!= break/disp8
14556         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
14557         89/<- %ebx 0/r32/eax
14558       }
14559       # var v2/eax: (addr v) = lookup(expected->value)
14560       (lookup *edx *(edx+4))  # List-value List-value => eax
14561       # var t2/eax: (addr type-tree) = lookup(v2->type)
14562       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14563       # if (t != t2) error
14564       (type-match? %eax %ebx *(ebp-4))  # => eax
14565       3d/compare-eax-and 0/imm32/false
14566       {
14567         0f 85/jump-if-!= break/disp32
14568         (write-buffered *(ebp+0x14) "fn ")
14569         8b/-> *(ebp+0x10) 0/r32/eax
14570         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14571         (write-buffered *(ebp+0x14) %eax)
14572         (write-buffered *(ebp+0x14) ": call ")
14573         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14574         (write-buffered *(ebp+0x14) %eax)
14575         (write-buffered *(ebp+0x14) ": type for inout '")
14576         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14577         (lookup *eax *(eax+4))  # Var-name Var-name => eax
14578         (write-buffered *(ebp+0x14) %eax)
14579         (write-buffered *(ebp+0x14) "' is not right\n")
14580         (flush *(ebp+0x14))
14581         (stop *(ebp+0x18) 1)
14582       }
14583 $check-mu-call:continue-to-next-inout:
14584       # inouts = lookup(inouts->next)
14585       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
14586       89/<- %ecx 0/r32/eax
14587       # expected = lookup(expected->next)
14588       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14589       89/<- %edx 0/r32/eax
14590       #
14591       e9/jump loop/disp32
14592     }
14593 $check-mu-call:check-inout-count:
14594     # if (inouts == expected) proceed
14595     39/compare %ecx 2/r32/edx
14596     {
14597       0f 84/jump-if-= break/disp32
14598       # exactly one of the two is null
14599       # if (inouts == 0) error("too many inouts")
14600       {
14601         81 7/subop/compare %ecx 0/imm32
14602         0f 84/jump-if-= break/disp32
14603         (write-buffered *(ebp+0x14) "fn ")
14604         8b/-> *(ebp+0x10) 0/r32/eax
14605         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14606         (write-buffered *(ebp+0x14) %eax)
14607         (write-buffered *(ebp+0x14) ": call ")
14608         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14609         (write-buffered *(ebp+0x14) %eax)
14610         (write-buffered *(ebp+0x14) ": too many inouts\n")
14611         (flush *(ebp+0x14))
14612         (stop *(ebp+0x18) 1)
14613       }
14614       # if (expected == 0) error("too few inouts")
14615       {
14616         81 7/subop/compare %edx 0/imm32
14617         0f 84/jump-if-= break/disp32
14618         (write-buffered *(ebp+0x14) "fn ")
14619         8b/-> *(ebp+0x10) 0/r32/eax
14620         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14621         (write-buffered *(ebp+0x14) %eax)
14622         (write-buffered *(ebp+0x14) ": call ")
14623         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14624         (write-buffered *(ebp+0x14) %eax)
14625         (write-buffered *(ebp+0x14) ": too few inouts\n")
14626         (flush *(ebp+0x14))
14627         (stop *(ebp+0x18) 1)
14628       }
14629     }
14630 $check-mu-call:check-outputs:
14631     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
14632     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
14633     89/<- %ecx 0/r32/eax
14634     # var expected/edx: (addr list var) = lookup(f->outputs)
14635     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
14636     89/<- %edx 0/r32/eax
14637     {
14638 $check-mu-call:check-for-outputs:
14639       # if (outputs == 0) break
14640       81 7/subop/compare %ecx 0/imm32
14641       0f 84/jump-if-= break/disp32
14642       # if (expected == 0) error
14643       81 7/subop/compare %edx 0/imm32
14644       0f 84/jump-if-= break/disp32
14645 $check-mu-call:check-output-type:
14646       # var v/eax: (addr v) = lookup(outputs->value)
14647       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14648       # var t/ebx: (addr type-tree) = lookup(v->type)
14649       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14650       89/<- %ebx 0/r32/eax
14651       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
14652       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
14653       {
14654         74/jump-if-= break/disp8
14655         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
14656         89/<- %ebx 0/r32/eax
14657       }
14658       # var v2/eax: (addr v) = lookup(expected->value)
14659       (lookup *edx *(edx+4))  # List-value List-value => eax
14660       # var t2/eax: (addr type-tree) = lookup(v2->type)
14661       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14662       # if (t != t2) error
14663       (type-match? %eax %ebx *(ebp-4))  # => eax
14664       3d/compare-eax-and 0/imm32/false
14665       {
14666         0f 85/jump-if-!= break/disp32
14667         (write-buffered *(ebp+0x14) "fn ")
14668         8b/-> *(ebp+0x10) 0/r32/eax
14669         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14670         (write-buffered *(ebp+0x14) %eax)
14671         (write-buffered *(ebp+0x14) ": call ")
14672         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14673         (write-buffered *(ebp+0x14) %eax)
14674         (write-buffered *(ebp+0x14) ": type for output '")
14675         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14676         (lookup *eax *(eax+4))  # Var-name Var-name => eax
14677         (write-buffered *(ebp+0x14) %eax)
14678         (write-buffered *(ebp+0x14) "' is not right\n")
14679         (flush *(ebp+0x14))
14680         (stop *(ebp+0x18) 1)
14681       }
14682 $check-mu-call:check-output-register:
14683       # var v/eax: (addr v) = lookup(outputs->value)
14684       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14685       # var r/ebx: (addr array byte) = lookup(v->register)
14686       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
14687       89/<- %ebx 0/r32/eax
14688       # if (r == 0) error
14689       3d/compare-eax-and 0/imm32
14690       {
14691         0f 85/jump-if-!= break/disp32
14692         (write-buffered *(ebp+0x14) "fn ")
14693         8b/-> *(ebp+0x10) 0/r32/eax
14694         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14695         (write-buffered *(ebp+0x14) %eax)
14696         (write-buffered *(ebp+0x14) ": call ")
14697         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14698         (write-buffered *(ebp+0x14) %eax)
14699         (write-buffered *(ebp+0x14) ": output '")
14700         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14701         (lookup *eax *(eax+4))  # Var-name Var-name => eax
14702         (write-buffered *(ebp+0x14) %eax)
14703         (write-buffered *(ebp+0x14) "' is not in a register\n")
14704         (flush *(ebp+0x14))
14705         (stop *(ebp+0x18) 1)
14706       }
14707       # var v2/eax: (addr v) = lookup(expected->value)
14708       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
14709       # var r2/eax: (addr array byte) = lookup(v2->register)
14710       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
14711       # if (r != r2) error
14712       (string-equal? %eax %ebx)  # => eax
14713       3d/compare-eax-and 0/imm32/false
14714       {
14715         0f 85/jump-if-!= break/disp32
14716         (write-buffered *(ebp+0x14) "fn ")
14717         8b/-> *(ebp+0x10) 0/r32/eax
14718         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14719         (write-buffered *(ebp+0x14) %eax)
14720         (write-buffered *(ebp+0x14) ": call ")
14721         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14722         (write-buffered *(ebp+0x14) %eax)
14723         (write-buffered *(ebp+0x14) ": register for output '")
14724         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
14725         (lookup *eax *(eax+4))  # Var-name Var-name => eax
14726         (write-buffered *(ebp+0x14) %eax)
14727         (write-buffered *(ebp+0x14) "' is not right\n")
14728         (flush *(ebp+0x14))
14729         (stop *(ebp+0x18) 1)
14730       }
14731 $check-mu-call:continue-to-next-output:
14732       # outputs = lookup(outputs->next)
14733       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
14734       89/<- %ecx 0/r32/eax
14735       # expected = lookup(expected->next)
14736       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
14737       89/<- %edx 0/r32/eax
14738       #
14739       e9/jump loop/disp32
14740     }
14741 $check-mu-call:check-output-count:
14742     # if (outputs == expected) proceed
14743     39/compare %ecx 2/r32/edx
14744     {
14745       0f 84/jump-if-= break/disp32
14746       # exactly one of the two is null
14747       # if (outputs == 0) error("too many outputs")
14748       {
14749         81 7/subop/compare %ecx 0/imm32
14750         0f 84/jump-if-= break/disp32
14751         (write-buffered *(ebp+0x14) "fn ")
14752         8b/-> *(ebp+0x10) 0/r32/eax
14753         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14754         (write-buffered *(ebp+0x14) %eax)
14755         (write-buffered *(ebp+0x14) ": call ")
14756         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14757         (write-buffered *(ebp+0x14) %eax)
14758         (write-buffered *(ebp+0x14) ": too many outputs\n")
14759         (flush *(ebp+0x14))
14760         (stop *(ebp+0x18) 1)
14761       }
14762       # if (expected == 0) error("too few outputs")
14763       {
14764         81 7/subop/compare %edx 0/imm32
14765         0f 84/jump-if-= break/disp32
14766         (write-buffered *(ebp+0x14) "fn ")
14767         8b/-> *(ebp+0x10) 0/r32/eax
14768         (lookup *eax *(eax+4))  # Function-name Function-name => eax
14769         (write-buffered *(ebp+0x14) %eax)
14770         (write-buffered *(ebp+0x14) ": call ")
14771         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14772         (write-buffered *(ebp+0x14) %eax)
14773         (write-buffered *(ebp+0x14) ": too few outputs\n")
14774         (flush *(ebp+0x14))
14775         (stop *(ebp+0x18) 1)
14776       }
14777     }
14778 $check-mu-call:end:
14779     # . restore registers
14780     5f/pop-to-edi
14781     5e/pop-to-esi
14782     5b/pop-to-ebx
14783     5a/pop-to-edx
14784     59/pop-to-ecx
14785     58/pop-to-eax
14786     # . reclaim locals exclusively on the stack
14787     81 0/subop/add %esp 0x70/imm32
14788     # . epilogue
14789     89/<- %esp 5/r32/ebp
14790     5d/pop-to-ebp
14791     c3/return
14792 
14793 # like type-equal? but takes literals into account
14794 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
14795     # . prologue
14796     55/push-ebp
14797     89/<- %ebp 4/r32/esp
14798     # if (call == literal) return true  # TODO: more precise
14799     (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
14800     3d/compare-eax-and 0/imm32/false
14801     b8/copy-to-eax 1/imm32/true
14802     75/jump-if-!= $type-match?:end/disp8
14803 $type-match?:baseline:
14804     # otherwise fall back
14805     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
14806 $type-match?:end:
14807     # . epilogue
14808     89/<- %esp 5/r32/ebp
14809     5d/pop-to-ebp
14810     c3/return
14811 
14812 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
14813     # . prologue
14814     55/push-ebp
14815     89/<- %ebp 4/r32/esp
14816     # . save registers
14817     51/push-ecx
14818     52/push-edx
14819     53/push-ebx
14820     # ecx = def
14821     8b/-> *(ebp+8) 1/r32/ecx
14822     # edx = call
14823     8b/-> *(ebp+0xc) 2/r32/edx
14824 $type-component-match?:compare-addr:
14825     # if (def == call) return true
14826     8b/-> %ecx 0/r32/eax  # Var-type
14827     39/compare %edx 0/r32/eax  # Var-type
14828     b8/copy-to-eax 1/imm32/true
14829     0f 84/jump-if-= $type-component-match?:end/disp32
14830     # if (def == 0) return false
14831     b8/copy-to-eax 0/imm32/false
14832     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
14833     0f 84/jump-if-= $type-component-match?:end/disp32
14834     # if (call == 0) return false
14835     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
14836     0f 84/jump-if-= $type-component-match?:end/disp32
14837     # if def is a type parameter, just check in type-parameters
14838     {
14839 $type-component-match?:check-type-parameter:
14840       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
14841       74/jump-if-= break/disp8
14842       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
14843       75/jump-if-!= break/disp8
14844 $type-component-match?:type-parameter:
14845       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
14846       e9/jump $type-component-match?:end/disp32
14847     }
14848     # if def is a list containing just a type parameter, just check in type-parameters
14849     {
14850 $type-component-match?:check-list-type-parameter:
14851       # if def is a list..
14852       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
14853       75/jump-if-!= break/disp8
14854       #   ..that's a singleton
14855       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
14856       75/jump-if-!= break/disp8
14857       #   ..and whose head is a type parameter
14858       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
14859       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
14860       74/jump-if-= break/disp8
14861       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
14862       75/jump-if-!= break/disp8
14863 $type-component-match?:list-type-parameter:
14864       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
14865       e9/jump $type-component-match?:end/disp32
14866     }
14867 $type-component-match?:compare-atom-state:
14868     # if (def->is-atom? != call->is-atom?) return false
14869     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
14870     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
14871     b8/copy-to-eax 0/imm32/false
14872     0f 85/jump-if-!= $type-component-match?:end/disp32
14873     # if def->is-atom? return (def->value == call->value)
14874     {
14875 $type-component-match?:check-atom:
14876       81 7/subop/compare %ebx 0/imm32/false
14877       74/jump-if-= break/disp8
14878 $type-component-match?:is-atom:
14879       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
14880       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
14881       0f 94/set-if-= %al
14882       81 4/subop/and %eax 0xff/imm32
14883       e9/jump $type-component-match?:end/disp32
14884     }
14885 $type-component-match?:check-left:
14886     # if (!type-component-match?(def->left, call->left)) return false
14887     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
14888     89/<- %ebx 0/r32/eax
14889     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
14890     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
14891     3d/compare-eax-and 0/imm32/false
14892     74/jump-if-= $type-component-match?:end/disp8
14893 $type-component-match?:check-right:
14894     # return type-component-match?(def->right, call->right)
14895     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
14896     89/<- %ebx 0/r32/eax
14897     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
14898     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
14899 $type-component-match?:end:
14900     # . restore registers
14901     5b/pop-to-ebx
14902     5a/pop-to-edx
14903     59/pop-to-ecx
14904     # . epilogue
14905     89/<- %esp 5/r32/ebp
14906     5d/pop-to-ebp
14907     c3/return
14908 
14909 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
14910     # . prologue
14911     55/push-ebp
14912     89/<- %ebp 4/r32/esp
14913     # . save registers
14914     51/push-ecx
14915     #
14916     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
14917     # if parameter wasn't saved, save it
14918     {
14919       81 7/subop/compare *eax 0/imm32
14920       75/jump-if-!= break/disp8
14921       8b/-> *(ebp+0x10) 1/r32/ecx
14922       89/<- *eax 1/r32/ecx
14923     }
14924     #
14925     (type-equal? *(ebp+0x10) *eax)  # => eax
14926 $type-parameter-match?:end:
14927     # . restore registers
14928     59/pop-to-ecx
14929     # . epilogue
14930     89/<- %esp 5/r32/ebp
14931     5d/pop-to-ebp
14932     c3/return
14933 
14934 size-of:  # v: (addr var) -> result/eax: int
14935     # . prologue
14936     55/push-ebp
14937     89/<- %ebp 4/r32/esp
14938     # . save registers
14939     51/push-ecx
14940     # var t/ecx: (addr type-tree) = lookup(v->type)
14941     8b/-> *(ebp+8) 1/r32/ecx
14942 #?     (write-buffered Stderr "size-of ")
14943 #?     (write-int32-hex-buffered Stderr %ecx)
14944 #?     (write-buffered Stderr Newline)
14945 #?     (write-buffered Stderr "type allocid: ")
14946 #?     (write-int32-hex-buffered Stderr *(ecx+8))
14947 #?     (write-buffered Stderr Newline)
14948 #?     (flush Stderr)
14949     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14950     89/<- %ecx 0/r32/eax
14951     # if is-mu-array?(t) return size-of-array(t)
14952     {
14953       (is-mu-array? %ecx)  # => eax
14954       3d/compare-eax-and 0/imm32/false
14955       74/jump-if-= break/disp8
14956       (size-of-array %ecx)  # => eax
14957       eb/jump $size-of:end/disp8
14958     }
14959     # if is-mu-stream?(t) return size-of-stream(t)
14960     {
14961       (is-mu-stream? %ecx)  # => eax
14962       3d/compare-eax-and 0/imm32/false
14963       74/jump-if-= break/disp8
14964       (size-of-stream %ecx)  # => eax
14965       eb/jump $size-of:end/disp8
14966     }
14967     # if (!t->is-atom?) t = lookup(t->left)
14968     {
14969       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
14970       75/jump-if-!= break/disp8
14971       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
14972       89/<- %ecx 0/r32/eax
14973     }
14974     # TODO: assert t->is-atom?
14975     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
14976 $size-of:end:
14977     # . restore registers
14978     59/pop-to-ecx
14979     # . epilogue
14980     89/<- %esp 5/r32/ebp
14981     5d/pop-to-ebp
14982     c3/return
14983 
14984 size-of-deref:  # v: (addr var) -> result/eax: int
14985     # . prologue
14986     55/push-ebp
14987     89/<- %ebp 4/r32/esp
14988     # . save registers
14989     51/push-ecx
14990     # var t/ecx: (addr type-tree) = lookup(v->type)
14991     8b/-> *(ebp+8) 1/r32/ecx
14992     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
14993     89/<- %ecx 0/r32/eax
14994     # TODO: assert(t is an addr)
14995     # t = lookup(t->right)
14996     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
14997     89/<- %ecx 0/r32/eax
14998     # if is-mu-array?(t) return size-of-array(t)
14999     {
15000       (is-mu-array? %ecx)  # => eax
15001       3d/compare-eax-and 0/imm32/false
15002       74/jump-if-= break/disp8
15003       (size-of-array %ecx)  # => eax
15004       eb/jump $size-of-deref:end/disp8
15005     }
15006     # if is-mu-stream?(t) return size-of-stream(t)
15007     {
15008       (is-mu-stream? %ecx)  # => eax
15009       3d/compare-eax-and 0/imm32/false
15010       74/jump-if-= break/disp8
15011       (size-of-stream %ecx)  # => eax
15012       eb/jump $size-of-deref:end/disp8
15013     }
15014     # if (!t->is-atom?) t = lookup(t->left)
15015     {
15016       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
15017       75/jump-if-!= break/disp8
15018       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15019       89/<- %ecx 0/r32/eax
15020     }
15021     # TODO: assert t->is-atom?
15022     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
15023 $size-of-deref:end:
15024     # . restore registers
15025     59/pop-to-ecx
15026     # . epilogue
15027     89/<- %esp 5/r32/ebp
15028     5d/pop-to-ebp
15029     c3/return
15030 
15031 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
15032     # . prologue
15033     55/push-ebp
15034     89/<- %ebp 4/r32/esp
15035     # . save registers
15036     51/push-ecx
15037     # ecx = t
15038     8b/-> *(ebp+8) 1/r32/ecx
15039     # if t->is-atom?, return false
15040     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
15041     75/jump-if-!= $is-mu-array?:return-false/disp8
15042     # if !t->left->is-atom?, return false
15043     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15044     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
15045     74/jump-if-= $is-mu-array?:return-false/disp8
15046     # return t->left->value == array
15047     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
15048     0f 94/set-if-= %al
15049     81 4/subop/and %eax 0xff/imm32
15050     eb/jump $is-mu-array?:end/disp8
15051 $is-mu-array?:return-false:
15052     b8/copy-to-eax 0/imm32/false
15053 $is-mu-array?:end:
15054     # . restore registers
15055     59/pop-to-ecx
15056     # . epilogue
15057     89/<- %esp 5/r32/ebp
15058     5d/pop-to-ebp
15059     c3/return
15060 
15061 # size of a statically allocated array where the size is part of the type expression
15062 size-of-array:  # a: (addr type-tree) -> result/eax: int
15063     # . prologue
15064     55/push-ebp
15065     89/<- %ebp 4/r32/esp
15066     # . save registers
15067     51/push-ecx
15068     52/push-edx
15069     #
15070     8b/-> *(ebp+8) 1/r32/ecx
15071     # TODO: assert that a->left is 'array'
15072     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
15073     89/<- %ecx 0/r32/eax
15074     # var elem-type/edx: type-id = a->right->left->value
15075     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15076     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
15077     # TODO: assert that a->right->right->left->value == size
15078     # var array-size/ecx: int = a->right->right->left->value-size
15079     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
15080     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15081     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
15082     # return 4 + array-size * size-of(elem-type)
15083     (size-of-type-id-as-array-element %edx)  # => eax
15084     f7 4/subop/multiply-into-edx-eax %ecx
15085     05/add-to-eax 4/imm32  # for array size
15086     # TODO: check edx for overflow
15087 $size-of-array:end:
15088     # . restore registers
15089     5a/pop-to-edx
15090     59/pop-to-ecx
15091     # . epilogue
15092     89/<- %esp 5/r32/ebp
15093     5d/pop-to-ebp
15094     c3/return
15095 
15096 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
15097     # . prologue
15098     55/push-ebp
15099     89/<- %ebp 4/r32/esp
15100     # . save registers
15101     51/push-ecx
15102     # ecx = t
15103     8b/-> *(ebp+8) 1/r32/ecx
15104     # if t->is-atom?, return false
15105     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
15106     75/jump-if-!= $is-mu-stream?:return-false/disp8
15107     # if !t->left->is-atom?, return false
15108     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15109     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
15110     74/jump-if-= $is-mu-stream?:return-false/disp8
15111     # return t->left->value == stream
15112     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
15113     0f 94/set-if-= %al
15114     81 4/subop/and %eax 0xff/imm32
15115     eb/jump $is-mu-stream?:end/disp8
15116 $is-mu-stream?:return-false:
15117     b8/copy-to-eax 0/imm32/false
15118 $is-mu-stream?:end:
15119     # . restore registers
15120     59/pop-to-ecx
15121     # . epilogue
15122     89/<- %esp 5/r32/ebp
15123     5d/pop-to-ebp
15124     c3/return
15125 
15126 # size of a statically allocated stream where the size is part of the type expression
15127 size-of-stream:  # a: (addr type-tree) -> result/eax: int
15128     # . prologue
15129     55/push-ebp
15130     89/<- %ebp 4/r32/esp
15131     #
15132     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
15133     05/add-to-eax 8/imm32  # for read/write pointers
15134 $size-of-stream:end:
15135     # . epilogue
15136     89/<- %esp 5/r32/ebp
15137     5d/pop-to-ebp
15138     c3/return
15139 
15140 size-of-type-id:  # t: type-id -> result/eax: int
15141     # . prologue
15142     55/push-ebp
15143     89/<- %ebp 4/r32/esp
15144     # . save registers
15145     51/push-ecx
15146     # var out/ecx: (handle typeinfo)
15147     68/push 0/imm32
15148     68/push 0/imm32
15149     89/<- %ecx 4/r32/esp
15150     # eax = t
15151     8b/-> *(ebp+8) 0/r32/eax
15152     # if t is a literal, return 0
15153     3d/compare-eax-and 0/imm32
15154     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
15155     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
15156     3d/compare-eax-and 8/imm32/byte
15157     {
15158       75/jump-if-!= break/disp8
15159       b8/copy-to-eax 4/imm32
15160       eb/jump $size-of-type-id:end/disp8
15161     }
15162     # if t is a handle, return 8
15163     3d/compare-eax-and 4/imm32/handle
15164     {
15165       75/jump-if-!= break/disp8
15166       b8/copy-to-eax 8/imm32
15167       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
15168     }
15169     # if t is a slice, return 8
15170     3d/compare-eax-and 0xc/imm32/slice
15171     {
15172       75/jump-if-!= break/disp8
15173       b8/copy-to-eax 8/imm32
15174       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
15175     }
15176     # if t is a user-defined type, return its size
15177     # TODO: support non-atom type
15178     (find-typeinfo %eax %ecx)
15179     {
15180       81 7/subop/compare *ecx 0/imm32
15181       74/jump-if-= break/disp8
15182 $size-of-type-id:user-defined:
15183       (lookup *ecx *(ecx+4))  # => eax
15184       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
15185       eb/jump $size-of-type-id:end/disp8
15186     }
15187     # otherwise return the word size
15188     b8/copy-to-eax 4/imm32
15189 $size-of-type-id:end:
15190     # . reclaim locals
15191     81 0/subop/add %esp 8/imm32
15192     # . restore registers
15193     59/pop-to-ecx
15194     # . epilogue
15195     89/<- %esp 5/r32/ebp
15196     5d/pop-to-ebp
15197     c3/return
15198 
15199 # Minor violation of our type system since it returns an addr. But we could
15200 # replace it with a handle some time.
15201 # Returns null if t is an atom.
15202 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
15203     # . prologue
15204     55/push-ebp
15205     89/<- %ebp 4/r32/esp
15206     # . save registers
15207     51/push-ecx
15208     # eax = 0
15209     b8/copy-to-eax 0/imm32
15210     # ecx = t
15211     8b/-> *(ebp+8) 1/r32/ecx
15212 $type-tail:check-atom:
15213     # if t->is-atom? return 0
15214     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
15215     0f 85/jump-if-!= $type-tail:end/disp32
15216     # var tail = t->right
15217     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
15218     89/<- %ecx 0/r32/eax
15219 $type-tail:check-singleton:
15220     # if (tail->right == 0) return tail->left
15221     {
15222       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
15223       75/jump-if-!= break/disp8
15224       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15225       e9/jump $type-tail:end/disp32
15226     }
15227     # if tail->right->left is an array-capacity, return tail->left
15228     {
15229 $type-tail:check-array-capacity:
15230       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
15231       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
15232       75/jump-if-!= break/disp8
15233 $type-tail:check-array-capacity-1:
15234       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15235       3d/compare-eax-and 0/imm32
15236       74/jump-if-= break/disp8
15237 $type-tail:check-array-capacity-2:
15238       (is-simple-mu-type? %eax 9)  # array-capacity => eax
15239       3d/compare-eax-and 0/imm32/false
15240       74/jump-if-= break/disp8
15241 $type-tail:array-capacity:
15242       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15243       eb/jump $type-tail:end/disp8
15244     }
15245 $type-tail:check-compound-left:
15246     # if !tail->left->is-atom? return tail->left
15247     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15248     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
15249     74/jump-if-= $type-tail:end/disp8
15250 $type-tail:return-tail:
15251     # return tail
15252     89/<- %eax 1/r32/ecx
15253 $type-tail:end:
15254     # . restore registers
15255     59/pop-to-ecx
15256     # . epilogue
15257     89/<- %esp 5/r32/ebp
15258     5d/pop-to-ebp
15259     c3/return
15260 
15261 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
15262     # . prologue
15263     55/push-ebp
15264     89/<- %ebp 4/r32/esp
15265     # . save registers
15266     51/push-ecx
15267     52/push-edx
15268     53/push-ebx
15269     # ecx = a
15270     8b/-> *(ebp+8) 1/r32/ecx
15271     # edx = b
15272     8b/-> *(ebp+0xc) 2/r32/edx
15273 $type-equal?:compare-addr:
15274     # if (a == b) return true
15275     8b/-> %ecx 0/r32/eax  # Var-type
15276     39/compare %edx 0/r32/eax  # Var-type
15277     b8/copy-to-eax 1/imm32/true
15278     0f 84/jump-if-= $type-equal?:end/disp32
15279 $type-equal?:compare-null-a:
15280     # if (a == 0) return false
15281     b8/copy-to-eax 0/imm32/false
15282     81 7/subop/compare %ecx 0/imm32
15283     0f 84/jump-if-= $type-equal?:end/disp32
15284 $type-equal?:compare-null-b:
15285     # if (b == 0) return false
15286     81 7/subop/compare %edx 0/imm32
15287     0f 84/jump-if-= $type-equal?:end/disp32
15288 $type-equal?:compare-atom-state:
15289     # if (a->is-atom? != b->is-atom?) return false
15290     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
15291     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
15292     b8/copy-to-eax 0/imm32/false
15293     0f 85/jump-if-!= $type-equal?:end/disp32
15294     # if a->is-atom? return (a->value == b->value)
15295     {
15296 $type-equal?:check-atom:
15297       81 7/subop/compare %ebx 0/imm32/false
15298       74/jump-if-= break/disp8
15299 $type-equal?:is-atom:
15300       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
15301       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
15302       0f 94/set-if-= %al
15303       81 4/subop/and %eax 0xff/imm32
15304       e9/jump $type-equal?:end/disp32
15305     }
15306 $type-equal?:check-left:
15307     # if (!type-equal?(a->left, b->left)) return false
15308     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
15309     89/<- %ebx 0/r32/eax
15310     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
15311     (type-equal? %eax %ebx)  # => eax
15312     3d/compare-eax-and 0/imm32/false
15313     74/jump-if-= $type-equal?:end/disp8
15314 $type-equal?:check-right:
15315     # return type-equal?(a->right, b->right)
15316     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
15317     89/<- %ebx 0/r32/eax
15318     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
15319     (type-equal? %eax %ebx)  # => eax
15320 $type-equal?:end:
15321     # . restore registers
15322     5b/pop-to-ebx
15323     5a/pop-to-edx
15324     59/pop-to-ecx
15325     # . epilogue
15326     89/<- %esp 5/r32/ebp
15327     5d/pop-to-ebp
15328     c3/return
15329 
15330 #######################################################
15331 # Code-generation
15332 #######################################################
15333 
15334 == data
15335 
15336 # Global state added to each var record when performing code-generation.
15337 Curr-local-stack-offset:  # (addr int)
15338     0/imm32
15339 
15340 == code
15341 
15342 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
15343     # . prologue
15344     55/push-ebp
15345     89/<- %ebp 4/r32/esp
15346     # . save registers
15347     50/push-eax
15348     # var curr/eax: (addr function) = *Program->functions
15349     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15350     {
15351       # if (curr == null) break
15352       3d/compare-eax-and 0/imm32
15353       0f 84/jump-if-= break/disp32
15354       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
15355       # curr = lookup(curr->next)
15356       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
15357       e9/jump loop/disp32
15358     }
15359 $emit-subx:end:
15360     # . restore registers
15361     58/pop-to-eax
15362     # . epilogue
15363     89/<- %esp 5/r32/ebp
15364     5d/pop-to-ebp
15365     c3/return
15366 
15367 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
15368     # . prologue
15369     55/push-ebp
15370     89/<- %ebp 4/r32/esp
15371     # some preprocessing
15372     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
15373     # . save registers
15374     50/push-eax
15375     51/push-ecx
15376     52/push-edx
15377     # initialize some global state
15378     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
15379     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
15380     # ecx = f
15381     8b/-> *(ebp+0xc) 1/r32/ecx
15382     # var vars/edx: (stack (addr var) 256)
15383     81 5/subop/subtract %esp 0xc00/imm32
15384     68/push 0xc00/imm32/size
15385     68/push 0/imm32/top
15386     89/<- %edx 4/r32/esp
15387     # var name/eax: (addr array byte) = lookup(f->name)
15388     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15389     #
15390     (write-buffered *(ebp+8) %eax)
15391     (write-buffered *(ebp+8) ":\n")
15392     (emit-subx-prologue *(ebp+8))
15393     # var body/eax: (addr block) = lookup(f->body)
15394     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
15395     #
15396     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
15397     (emit-subx-epilogue *(ebp+8))
15398     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
15399     # been cleaned up
15400 $emit-subx-function:end:
15401     # . reclaim locals
15402     81 0/subop/add %esp 0xc08/imm32
15403     # . restore registers
15404     5a/pop-to-edx
15405     59/pop-to-ecx
15406     58/pop-to-eax
15407     # . epilogue
15408     89/<- %esp 5/r32/ebp
15409     5d/pop-to-ebp
15410     c3/return
15411 
15412 populate-mu-type-offsets-in-inouts:  # f: (addr function)
15413     # . prologue
15414     55/push-ebp
15415     89/<- %ebp 4/r32/esp
15416     # . save registers
15417     50/push-eax
15418     51/push-ecx
15419     52/push-edx
15420     53/push-ebx
15421     57/push-edi
15422     # var next-offset/edx: int = 8
15423     ba/copy-to-edx 8/imm32
15424     # var curr/ecx: (addr list var) = lookup(f->inouts)
15425     8b/-> *(ebp+8) 1/r32/ecx
15426     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15427     89/<- %ecx 0/r32/eax
15428     {
15429 $populate-mu-type-offsets-in-inouts:loop:
15430       81 7/subop/compare %ecx 0/imm32
15431       74/jump-if-= break/disp8
15432       # var v/ebx: (addr var) = lookup(curr->value)
15433       (lookup *ecx *(ecx+4))  # List-value List-value => eax
15434       89/<- %ebx 0/r32/eax
15435 #?       (lookup *ebx *(ebx+4))
15436 #?       (write-buffered Stderr "setting offset of fn inout ")
15437 #?       (write-buffered Stderr %eax)
15438 #?       (write-buffered Stderr "@")
15439 #?       (write-int32-hex-buffered Stderr %ebx)
15440 #?       (write-buffered Stderr " to ")
15441 #?       (write-int32-hex-buffered Stderr %edx)
15442 #?       (write-buffered Stderr Newline)
15443 #?       (flush Stderr)
15444       # v->offset = next-offset
15445       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
15446       # next-offset += size-of(v)
15447       (size-of %ebx)  # => eax
15448       01/add-to %edx 0/r32/eax
15449       # curr = lookup(curr->next)
15450       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
15451       89/<- %ecx 0/r32/eax
15452       #
15453       eb/jump loop/disp8
15454     }
15455 $populate-mu-type-offsets-in-inouts:end:
15456     # . restore registers
15457     5f/pop-to-edi
15458     5b/pop-to-ebx
15459     5a/pop-to-edx
15460     59/pop-to-ecx
15461     58/pop-to-eax
15462     # . epilogue
15463     89/<- %esp 5/r32/ebp
15464     5d/pop-to-ebp
15465     c3/return
15466 
15467 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)
15468     # . prologue
15469     55/push-ebp
15470     89/<- %ebp 4/r32/esp
15471     # . save registers
15472     50/push-eax
15473     51/push-ecx
15474     53/push-ebx
15475     56/push-esi
15476     # esi = stmts
15477     8b/-> *(ebp+0xc) 6/r32/esi
15478     #
15479     {
15480 $emit-subx-stmt-list:loop:
15481       81 7/subop/compare %esi 0/imm32
15482       0f 84/jump-if-= break/disp32
15483       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
15484       (lookup *esi *(esi+4))  # List-value List-value => eax
15485       89/<- %ecx 0/r32/eax
15486       {
15487 $emit-subx-stmt-list:check-for-block:
15488         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
15489         75/jump-if-!= break/disp8
15490 $emit-subx-stmt-list:block:
15491         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
15492       }
15493       {
15494 $emit-subx-stmt-list:check-for-stmt:
15495         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
15496         0f 85/jump-if-!= break/disp32
15497 $emit-subx-stmt-list:stmt1:
15498         {
15499           (is-mu-branch? %ecx)  # => eax
15500           3d/compare-eax-and 0/imm32/false
15501           0f 84/jump-if-= break/disp32
15502 $emit-subx-stmt-list:branch-stmt:
15503 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
15530 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
15546 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
15584 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
15603         }
15604 $emit-subx-stmt-list:1-to-1:
15605         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
15606         e9/jump $emit-subx-stmt-list:continue/disp32
15607       }
15608       {
15609 $emit-subx-stmt-list:check-for-var-def:
15610         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
15611         75/jump-if-!= break/disp8
15612 $emit-subx-stmt-list:var-def:
15613         (emit-subx-var-def *(ebp+8) %ecx)
15614         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
15615         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
15616         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
15617         #
15618         eb/jump $emit-subx-stmt-list:continue/disp8
15619       }
15620       {
15621 $emit-subx-stmt-list:check-for-reg-var-def:
15622         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
15623         0f 85/jump-if-!= break/disp32
15624 $emit-subx-stmt-list:reg-var-def:
15625         # TODO: ensure that there's exactly one output
15626         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
15627         # emit the instruction as usual
15628         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
15629         #
15630         eb/jump $emit-subx-stmt-list:continue/disp8
15631       }
15632 $emit-subx-stmt-list:continue:
15633       # TODO: raise an error on unrecognized Stmt-tag
15634       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
15635       89/<- %esi 0/r32/eax
15636       e9/jump loop/disp32
15637     }
15638 $emit-subx-stmt-list:emit-cleanup:
15639     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
15640 $emit-subx-stmt-list:clean-up:
15641     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
15642     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
15643 $emit-subx-stmt-list:end:
15644     # . restore registers
15645     5e/pop-to-esi
15646     5b/pop-to-ebx
15647     59/pop-to-ecx
15648     58/pop-to-eax
15649     # . epilogue
15650     89/<- %esp 5/r32/ebp
15651     5d/pop-to-ebp
15652     c3/return
15653 
15654 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
15655 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)
15656     # . prologue
15657     55/push-ebp
15658     89/<- %ebp 4/r32/esp
15659     # . save registers
15660     50/push-eax
15661     51/push-ecx
15662     52/push-edx
15663     # ecx = stmt
15664     8b/-> *(ebp+0xc) 1/r32/ecx
15665     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
15666     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
15667     # TODO: assert !sv->is-deref?
15668     # var v/ecx: (addr var) = lookup(sv->value)
15669     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15670     89/<- %ecx 0/r32/eax
15671     # v->block-depth = *Curr-block-depth
15672     8b/-> *Curr-block-depth 0/r32/eax
15673     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
15674 #?     (write-buffered Stderr "var ")
15675 #?     (lookup *ecx *(ecx+4))
15676 #?     (write-buffered Stderr %eax)
15677 #?     (write-buffered Stderr " at depth ")
15678 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
15679 #?     (write-buffered Stderr Newline)
15680 #?     (flush Stderr)
15681     # ensure that v is in a register
15682     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
15683     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
15684     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
15685     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
15686     89/<- %edx 0/r32/eax
15687     3d/compare-eax-and 0/imm32/false
15688     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
15689     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
15690     89/<- %edx 0/r32/eax
15691     # check emit-spill?
15692     3d/compare-eax-and 0/imm32/false
15693     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
15694     # TODO: assert(size-of(output) == 4)
15695     # *Curr-local-stack-offset -= 4
15696     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
15697     # emit spill
15698     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
15699     (emit-push-register *(ebp+8) %eax)
15700 $push-output-and-maybe-emit-spill:push:
15701     8b/-> *(ebp+0xc) 1/r32/ecx
15702     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
15703     # push(vars, {sv->value, emit-spill?})
15704     (push *(ebp+0x10) *eax)  # Stmt-var-value
15705     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
15706     (push *(ebp+0x10) %edx)
15707 $push-output-and-maybe-emit-spill:end:
15708     # . restore registers
15709     5a/pop-to-edx
15710     59/pop-to-ecx
15711     58/pop-to-eax
15712     # . epilogue
15713     89/<- %esp 5/r32/ebp
15714     5d/pop-to-ebp
15715     c3/return
15716 
15717 $push-output-and-maybe-emit-spill:abort:
15718     # error("var '" var->name "' initialized from an instruction must live in a register\n")
15719     (write-buffered *(ebp+0x1c) "var '")
15720     (write-buffered *(ebp+0x1c) *eax)  # Var-name
15721     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
15722     (flush *(ebp+0x1c))
15723     (stop *(ebp+0x20) 1)
15724     # never gets here
15725 
15726 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
15727     # . prologue
15728     55/push-ebp
15729     89/<- %ebp 4/r32/esp
15730     # . save registers
15731     50/push-eax
15732     51/push-ecx
15733     # ecx = stmt
15734     8b/-> *(ebp+0xc) 1/r32/ecx
15735     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
15736     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
15737     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
15738     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15739     # clean up until target block
15740     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
15741     # emit jump to target block
15742     (emit-indent *(ebp+8) *Curr-block-depth)
15743     (write-buffered *(ebp+8) "e9/jump ")
15744     (write-buffered *(ebp+8) %eax)
15745     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
15746     (string-starts-with? %eax "break")
15747     3d/compare-eax-and 0/imm32/false
15748     {
15749       74/jump-if-= break/disp8
15750       (write-buffered *(ebp+8) ":break/disp32\n")
15751     }
15752     3d/compare-eax-and 0/imm32/false  # just in case the function call modified flags
15753     {
15754       75/jump-if-!= break/disp8
15755       (write-buffered *(ebp+8) ":loop/disp32\n")
15756     }
15757 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
15758     # . restore registers
15759     59/pop-to-ecx
15760     58/pop-to-eax
15761     # . epilogue
15762     89/<- %esp 5/r32/ebp
15763     5d/pop-to-ebp
15764     c3/return
15765 
15766 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
15767     # . prologue
15768     55/push-ebp
15769     89/<- %ebp 4/r32/esp
15770     # . save registers
15771     51/push-ecx
15772     # ecx = lookup(stmt->operation)
15773     8b/-> *(ebp+8) 1/r32/ecx
15774     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
15775     89/<- %ecx 0/r32/eax
15776     # if (stmt->operation starts with "loop") return true
15777     (string-starts-with? %ecx "loop")  # => eax
15778     3d/compare-eax-and 0/imm32/false
15779     75/jump-if-not-equal $is-mu-branch?:end/disp8
15780     # otherwise return (stmt->operation starts with "break")
15781     (string-starts-with? %ecx "break")  # => eax
15782 $is-mu-branch?:end:
15783     # . restore registers
15784     59/pop-to-ecx
15785     # . epilogue
15786     89/<- %esp 5/r32/ebp
15787     5d/pop-to-ebp
15788     c3/return
15789 
15790 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
15791     # . prologue
15792     55/push-ebp
15793     89/<- %ebp 4/r32/esp
15794     # . save registers
15795     50/push-eax
15796     # eax = stmt
15797     8b/-> *(ebp+0xc) 0/r32/eax
15798     #
15799     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
15800     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
15801     (emit-indent *(ebp+8) *Curr-block-depth)
15802     (lookup *eax *(eax+4))  # => eax
15803     (write-buffered *(ebp+8) %eax)
15804     (write-buffered *(ebp+8) " break/disp32\n")
15805 $emit-reverse-break:end:
15806     # . restore registers
15807     58/pop-to-eax
15808     # . epilogue
15809     89/<- %esp 5/r32/ebp
15810     5d/pop-to-ebp
15811     c3/return
15812 
15813 == data
15814 
15815 # Table from Mu branch instructions to the reverse SubX opcodes for them.
15816 Reverse-branch:  # (table (handle array byte) (handle array byte))
15817   # a table is a stream
15818   0x1c0/imm32/write
15819   0/imm32/read
15820   0x1c0/imm32/size
15821   # data
15822   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
15823   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
15824   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
15825   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
15826   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
15827   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
15828   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
15829   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
15830   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
15831   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
15832   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
15833   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
15834   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
15835   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
15836   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
15837   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
15838   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
15839   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
15840   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
15841   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
15842   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
15843   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
15844   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
15845   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
15846   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
15847   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
15848   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
15849   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
15850 
15851 == code
15852 
15853 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
15854     # . prologue
15855     55/push-ebp
15856     89/<- %ebp 4/r32/esp
15857     # . save registers
15858     50/push-eax
15859     51/push-ecx
15860     52/push-edx
15861     53/push-ebx
15862     56/push-esi
15863     # ecx = vars
15864     8b/-> *(ebp+0xc) 1/r32/ecx
15865     # var eax: int = vars->top
15866     8b/-> *ecx 0/r32/eax
15867     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
15868     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
15869     # var min/ecx: (addr handle var) = vars->data
15870     8d/copy-address *(ecx+8) 1/r32/ecx
15871     # edx = depth
15872     8b/-> *(ebp+0x10) 2/r32/edx
15873     {
15874 $emit-unconditional-jump-to-depth:loop:
15875       # if (curr < min) break
15876       39/compare %esi 1/r32/ecx
15877       0f 82/jump-if-addr< break/disp32
15878       # var v/ebx: (addr var) = lookup(*curr)
15879       (lookup *esi *(esi+4))  # => eax
15880       89/<- %ebx 0/r32/eax
15881       # if (v->block-depth < until-block-depth) break
15882       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
15883       0f 8c/jump-if-< break/disp32
15884       {
15885 $emit-unconditional-jump-to-depth:check:
15886         # if v->block-depth != until-block-depth, continue
15887         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
15888         0f 85/jump-if-!= break/disp32
15889 $emit-unconditional-jump-to-depth:depth-found:
15890         # if v is not a literal, continue
15891         (size-of %ebx)  # => eax
15892         3d/compare-eax-and 0/imm32
15893         0f 85/jump-if-!= break/disp32
15894 $emit-unconditional-jump-to-depth:label-found:
15895         # emit unconditional jump, then return
15896         (emit-indent *(ebp+8) *Curr-block-depth)
15897         (write-buffered *(ebp+8) "e9/jump ")
15898         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15899         (write-buffered *(ebp+8) %eax)
15900         (write-buffered *(ebp+8) ":")
15901         (write-buffered *(ebp+8) *(ebp+0x14))
15902         (write-buffered *(ebp+8) "/disp32\n")
15903         eb/jump $emit-unconditional-jump-to-depth:end/disp8
15904       }
15905       # curr -= 12
15906       81 5/subop/subtract %esi 0xc/imm32
15907       e9/jump loop/disp32
15908     }
15909     # TODO: error if no label at 'depth' was found
15910 $emit-unconditional-jump-to-depth:end:
15911     # . restore registers
15912     5e/pop-to-esi
15913     5b/pop-to-ebx
15914     5a/pop-to-edx
15915     59/pop-to-ecx
15916     58/pop-to-eax
15917     # . epilogue
15918     89/<- %esp 5/r32/ebp
15919     5d/pop-to-ebp
15920     c3/return
15921 
15922 # emit clean-up code for 'vars' until some block depth
15923 # doesn't actually modify 'vars' so we need traverse manually inside the stack
15924 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
15925     # . prologue
15926     55/push-ebp
15927     89/<- %ebp 4/r32/esp
15928     # . save registers
15929     50/push-eax
15930     51/push-ecx
15931     52/push-edx
15932     53/push-ebx
15933     56/push-esi
15934 #?     (write-buffered Stderr "--- cleanup\n")
15935 #?     (flush Stderr)
15936     # ecx = vars
15937     8b/-> *(ebp+0xc) 1/r32/ecx
15938     # var esi: int = vars->top
15939     8b/-> *ecx 6/r32/esi
15940     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
15941     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
15942     # var min/ecx: (addr handle var) = vars->data
15943     81 0/subop/add %ecx 8/imm32
15944     # edx = until-block-depth
15945     8b/-> *(ebp+0x10) 2/r32/edx
15946     {
15947 $emit-cleanup-code-until-depth:loop:
15948       # if (curr < min) break
15949       39/compare %esi 1/r32/ecx
15950       0f 82/jump-if-addr< break/disp32
15951       # var v/ebx: (addr var) = lookup(*curr)
15952       (lookup *esi *(esi+4))  # => eax
15953       89/<- %ebx 0/r32/eax
15954 #?       (lookup *ebx *(ebx+4))  # Var-name
15955 #?       (write-buffered Stderr "var ")
15956 #?       (write-buffered Stderr %eax)
15957 #?       (write-buffered Stderr Newline)
15958 #?       (flush Stderr)
15959       # if (v->block-depth < until-block-depth) break
15960       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
15961       0f 8c/jump-if-< break/disp32
15962       # if v is in a register
15963       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
15964       {
15965         0f 84/jump-if-= break/disp32
15966         {
15967 $emit-cleanup-code-until-depth:check-for-previous-spill:
15968           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
15969           3d/compare-eax-and 0/imm32/false
15970           74/jump-if-= break/disp8
15971 $emit-cleanup-code-until-depth:reclaim-var-in-register:
15972           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15973           (emit-pop-register *(ebp+8) %eax)
15974         }
15975         eb/jump $emit-cleanup-code-until-depth:continue/disp8
15976       }
15977       # otherwise v is on the stack
15978       {
15979         75/jump-if-!= break/disp8
15980 $emit-cleanup-code-until-depth:var-on-stack:
15981         (size-of %ebx)  # => eax
15982         # don't emit code for labels
15983         3d/compare-eax-and 0/imm32
15984         74/jump-if-= break/disp8
15985 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
15986         (emit-indent *(ebp+8) *Curr-block-depth)
15987         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
15988         (write-int32-hex-buffered *(ebp+8) %eax)
15989         (write-buffered *(ebp+8) "/imm32\n")
15990       }
15991 $emit-cleanup-code-until-depth:continue:
15992       # curr -= 12
15993       81 5/subop/subtract %esi 0xc/imm32
15994       e9/jump loop/disp32
15995     }
15996 $emit-cleanup-code-until-depth:end:
15997     # . restore registers
15998     5e/pop-to-esi
15999     5b/pop-to-ebx
16000     5a/pop-to-edx
16001     59/pop-to-ecx
16002     58/pop-to-eax
16003     # . epilogue
16004     89/<- %esp 5/r32/ebp
16005     5d/pop-to-ebp
16006     c3/return
16007 
16008 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
16009     # . prologue
16010     55/push-ebp
16011     89/<- %ebp 4/r32/esp
16012     # eax = reg
16013     8b/-> *(ebp+0xc) 0/r32/eax
16014     # var prefix/eax: byte = reg->data[0]
16015     8a/copy-byte *(eax+4) 0/r32/AL
16016     81 4/subop/and %eax 0xff/imm32
16017     # if (prefix == 'x') push xmm register
16018     {
16019       3d/compare-eax-and 0x78/imm32/x
16020       0f 85/jump-if-!= break/disp32
16021       # TODO validate register
16022       (emit-indent *(ebp+8) *Curr-block-depth)
16023       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
16024       (emit-indent *(ebp+8) *Curr-block-depth)
16025       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
16026       # var prefix/eax: byte = reg->data[3]
16027       8b/-> *(ebp+0xc) 0/r32/eax
16028       8a/copy-byte *(eax+7) 0/r32/AL
16029       81 4/subop/and %eax 0xff/imm32
16030       (write-byte-buffered *(ebp+8) %eax)
16031       (write-buffered *(ebp+8) "/x32\n")
16032       e9/jump $emit-push-register:end/disp32
16033     }
16034     # otherwise push gp register
16035     (emit-indent *(ebp+8) *Curr-block-depth)
16036     (write-buffered *(ebp+8) "ff 6/subop/push %")
16037     (write-buffered *(ebp+8) *(ebp+0xc))
16038     (write-buffered *(ebp+8) Newline)
16039 $emit-push-register:end:
16040     # . epilogue
16041     89/<- %esp 5/r32/ebp
16042     5d/pop-to-ebp
16043     c3/return
16044 
16045 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
16046     # . prologue
16047     55/push-ebp
16048     89/<- %ebp 4/r32/esp
16049     # eax = reg
16050     8b/-> *(ebp+0xc) 0/r32/eax
16051     # var prefix/eax: byte = reg->data[0]
16052     8a/copy-byte *(eax+4) 0/r32/AL
16053     81 4/subop/and %eax 0xff/imm32
16054     # if (prefix == 'x') pop to xmm register
16055     {
16056       3d/compare-eax-and 0x78/imm32/x
16057       0f 85/jump-if-!= break/disp32
16058       # TODO validate register
16059       (emit-indent *(ebp+8) *Curr-block-depth)
16060       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
16061       # var prefix/eax: byte = reg->data[3]
16062       8b/-> *(ebp+0xc) 0/r32/eax
16063       8a/copy-byte *(eax+7) 0/r32/AL
16064       81 4/subop/and %eax 0xff/imm32
16065       (write-byte-buffered *(ebp+8) %eax)
16066       (write-buffered *(ebp+8) "/x32\n")
16067       (emit-indent *(ebp+8) *Curr-block-depth)
16068       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
16069       e9/jump $emit-push-register:end/disp32
16070     }
16071     # otherwise pop to gp register
16072     (emit-indent *(ebp+8) *Curr-block-depth)
16073     (write-buffered *(ebp+8) "8f 0/subop/pop %")
16074     (write-buffered *(ebp+8) *(ebp+0xc))
16075     (write-buffered *(ebp+8) Newline)
16076 $emit-pop-register:end:
16077     # . epilogue
16078     89/<- %esp 5/r32/ebp
16079     5d/pop-to-ebp
16080     c3/return
16081 
16082 # emit clean-up code for 'vars' until a given label is encountered
16083 # doesn't actually modify 'vars' so we need traverse manually inside the stack
16084 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
16085     # . prologue
16086     55/push-ebp
16087     89/<- %ebp 4/r32/esp
16088     # . save registers
16089     50/push-eax
16090     51/push-ecx
16091     52/push-edx
16092     53/push-ebx
16093     # ecx = vars
16094     8b/-> *(ebp+0xc) 1/r32/ecx
16095     # var eax: int = vars->top
16096     8b/-> *ecx 0/r32/eax
16097     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
16098     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
16099     # var min/ecx: (addr handle var) = vars->data
16100     81 0/subop/add %ecx 8/imm32
16101     {
16102 $emit-cleanup-code-until-target:loop:
16103       # if (curr < min) break
16104       39/compare %edx 1/r32/ecx
16105       0f 82/jump-if-addr< break/disp32
16106       # var v/ebx: (handle var) = lookup(*curr)
16107       (lookup *edx *(edx+4))  # => eax
16108       89/<- %ebx 0/r32/eax
16109       # if (v->name == until-block-label) break
16110       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
16111       (string-equal? %eax *(ebp+0x10))  # => eax
16112       3d/compare-eax-and 0/imm32/false
16113       0f 85/jump-if-!= break/disp32
16114       # if v is in a register
16115       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
16116       {
16117         0f 84/jump-if-= break/disp32
16118         {
16119 $emit-cleanup-code-until-target:check-for-previous-spill:
16120           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
16121           3d/compare-eax-and 0/imm32/false
16122           74/jump-if-= break/disp8
16123 $emit-cleanup-code-until-target:reclaim-var-in-register:
16124           (emit-indent *(ebp+8) *Curr-block-depth)
16125           (write-buffered *(ebp+8) "8f 0/subop/pop %")
16126           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
16127           (write-buffered *(ebp+8) %eax)
16128           (write-buffered *(ebp+8) Newline)
16129         }
16130         eb/jump $emit-cleanup-code-until-target:continue/disp8
16131       }
16132       # otherwise v is on the stack
16133       {
16134         75/jump-if-!= break/disp8
16135 $emit-cleanup-code-until-target:reclaim-var-on-stack:
16136         (size-of %ebx)  # => eax
16137         # don't emit code for labels
16138         3d/compare-eax-and 0/imm32
16139         74/jump-if-= break/disp8
16140         #
16141         (emit-indent *(ebp+8) *Curr-block-depth)
16142         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
16143         (write-int32-hex-buffered *(ebp+8) %eax)
16144         (write-buffered *(ebp+8) "/imm32\n")
16145       }
16146 $emit-cleanup-code-until-target:continue:
16147       # curr -= 12
16148       81 5/subop/subtract %edx 0xc/imm32
16149       e9/jump loop/disp32
16150     }
16151 $emit-cleanup-code-until-target:end:
16152     # . restore registers
16153     5b/pop-to-ebx
16154     5a/pop-to-edx
16155     59/pop-to-ecx
16156     58/pop-to-eax
16157     # . epilogue
16158     89/<- %esp 5/r32/ebp
16159     5d/pop-to-ebp
16160     c3/return
16161 
16162 # update Curr-local-stack-offset assuming vars until some block depth are popped
16163 # doesn't actually modify 'vars', so we need traverse manually inside the stack
16164 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
16165     # . prologue
16166     55/push-ebp
16167     89/<- %ebp 4/r32/esp
16168     # . save registers
16169     50/push-eax
16170     51/push-ecx
16171     52/push-edx
16172     53/push-ebx
16173     56/push-esi
16174     # ecx = vars
16175     8b/-> *(ebp+8) 1/r32/ecx
16176     # var esi: int = vars->top
16177     8b/-> *ecx 6/r32/esi
16178     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
16179     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
16180     # var min/ecx: (addr handle var) = vars->data
16181     81 0/subop/add %ecx 8/imm32
16182     # edx = until-block-depth
16183     8b/-> *(ebp+0xc) 2/r32/edx
16184     {
16185 $clean-up-stack-offset-state:loop:
16186       # if (curr < min) break
16187       39/compare %esi 1/r32/ecx
16188       0f 82/jump-if-addr< break/disp32
16189       # var v/ebx: (addr var) = lookup(*curr)
16190       (lookup *esi *(esi+4))  # => eax
16191       89/<- %ebx 0/r32/eax
16192       # if (v->block-depth < until-block-depth) break
16193       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
16194       0f 8c/jump-if-< break/disp32
16195       # if v is in a register
16196       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
16197       {
16198         0f 84/jump-if-= break/disp32
16199         {
16200 $clean-up-stack-offset-state:check-for-previous-spill:
16201           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
16202           3d/compare-eax-and 0/imm32/false
16203           74/jump-if-= break/disp8
16204 $clean-up-stack-offset-state:reclaim-var-in-register:
16205           81 0/subop/add *Curr-local-stack-offset 4/imm32
16206         }
16207         eb/jump $clean-up-stack-offset-state:continue/disp8
16208       }
16209       # otherwise v is on the stack
16210       {
16211         75/jump-if-!= break/disp8
16212 $clean-up-stack-offset-state:var-on-stack:
16213         (size-of %ebx)  # => eax
16214         01/add-to *Curr-local-stack-offset 0/r32/eax
16215       }
16216 $clean-up-stack-offset-state:continue:
16217       # curr -= 12
16218       81 5/subop/subtract %esi 0xc/imm32
16219       e9/jump loop/disp32
16220     }
16221 $clean-up-stack-offset-state:end:
16222     # . restore registers
16223     5e/pop-to-esi
16224     5b/pop-to-ebx
16225     5a/pop-to-edx
16226     59/pop-to-ecx
16227     58/pop-to-eax
16228     # . epilogue
16229     89/<- %esp 5/r32/ebp
16230     5d/pop-to-ebp
16231     c3/return
16232 
16233 # Return true if there isn't a variable in 'vars' with the same block-depth
16234 # and register as 'v'.
16235 # 'v' is guaranteed not to be within 'vars'.
16236 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
16237     # . prologue
16238     55/push-ebp
16239     89/<- %ebp 4/r32/esp
16240     # . save registers
16241     51/push-ecx
16242     52/push-edx
16243     53/push-ebx
16244     56/push-esi
16245     57/push-edi
16246     # ecx = vars
16247     8b/-> *(ebp+0xc) 1/r32/ecx
16248     # var eax: int = vars->top
16249     8b/-> *ecx 0/r32/eax
16250     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
16251     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
16252     # var min/ecx: (addr handle var) = vars->data
16253     8d/copy-address *(ecx+8) 1/r32/ecx
16254     # var depth/ebx: int = v->block-depth
16255     8b/-> *(ebp+8) 3/r32/ebx
16256     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
16257     # var needle/esi: (addr array byte) = v->register
16258     8b/-> *(ebp+8) 6/r32/esi
16259     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
16260     89/<- %esi 0/r32/eax
16261     {
16262 $not-yet-spilled-this-block?:loop:
16263       # if (curr < min) break
16264       39/compare %edx 1/r32/ecx
16265       0f 82/jump-if-addr< break/disp32
16266       # var cand/edi: (addr var) = lookup(*curr)
16267       (lookup *edx *(edx+4))  # => eax
16268       89/<- %edi 0/r32/eax
16269       # if (cand->block-depth < depth) break
16270       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
16271       0f 8c/jump-if-< break/disp32
16272       # var cand-reg/edi: (array array byte) = cand->reg
16273       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
16274       89/<- %edi 0/r32/eax
16275       # if (cand-reg == null) continue
16276       {
16277 $not-yet-spilled-this-block?:check-reg:
16278         81 7/subop/compare %edi 0/imm32
16279         0f 84/jump-if-= break/disp32
16280         # if (cand-reg == needle) return true
16281         (string-equal? %esi %edi)  # => eax
16282         3d/compare-eax-and 0/imm32/false
16283         74/jump-if-= break/disp8
16284 $not-yet-spilled-this-block?:return-false:
16285         b8/copy-to-eax 0/imm32/false
16286         eb/jump $not-yet-spilled-this-block?:end/disp8
16287       }
16288 $not-yet-spilled-this-block?:continue:
16289       # curr -= 12
16290       81 5/subop/subtract %edx 0xc/imm32
16291       e9/jump loop/disp32
16292     }
16293 $not-yet-spilled-this-block?:return-true:
16294     # return true
16295     b8/copy-to-eax 1/imm32/true
16296 $not-yet-spilled-this-block?:end:
16297     # . restore registers
16298     5f/pop-to-edi
16299     5e/pop-to-esi
16300     5b/pop-to-ebx
16301     5a/pop-to-edx
16302     59/pop-to-ecx
16303     # . epilogue
16304     89/<- %esp 5/r32/ebp
16305     5d/pop-to-ebp
16306     c3/return
16307 
16308 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
16309 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
16310     # . prologue
16311     55/push-ebp
16312     89/<- %ebp 4/r32/esp
16313     # eax = v
16314     8b/-> *(ebp+8) 0/r32/eax
16315     # var reg/eax: (addr array byte) = lookup(v->register)
16316     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16317     # var target/eax: (addr var) = find-register(fn-outputs, reg)
16318     (find-register *(ebp+0x10) %eax)  # => eax
16319     # if (target == 0) return true
16320     {
16321       3d/compare-eax-and 0/imm32
16322       75/jump-if-!= break/disp8
16323       b8/copy-to-eax 1/imm32/true
16324       eb/jump $will-not-write-some-register?:end/disp8
16325     }
16326     # return !assigns-in-stmts?(stmts, target)
16327     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
16328     3d/compare-eax-and 0/imm32/false
16329     # assume: true = 1, so no need to mask with 0x000000ff
16330     0f 94/set-if-= %al
16331 $will-not-write-some-register?:end:
16332     # . epilogue
16333     89/<- %esp 5/r32/ebp
16334     5d/pop-to-ebp
16335     c3/return
16336 
16337 # return fn output with matching register
16338 # always returns false if 'reg' is null
16339 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
16340     # . prologue
16341     55/push-ebp
16342     89/<- %ebp 4/r32/esp
16343     # . save registers
16344     51/push-ecx
16345     # var curr/ecx: (addr list var) = lookup(fn->outputs)
16346     8b/-> *(ebp+8) 1/r32/ecx
16347     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16348     89/<- %ecx 0/r32/eax
16349     {
16350 $find-register:loop:
16351       # if (curr == 0) break
16352       81 7/subop/compare %ecx 0/imm32
16353       74/jump-if-= break/disp8
16354       # eax = curr->value->register
16355       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16356       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16357       # if (eax == reg) return curr->value
16358 $find-register:compare:
16359       (string-equal? *(ebp+0xc) %eax)  # => eax
16360       {
16361         3d/compare-eax-and 0/imm32/false
16362         74/jump-if-= break/disp8
16363 $find-register:found:
16364         (lookup *ecx *(ecx+4))  # List-value List-value => eax
16365         eb/jump $find-register:end/disp8
16366       }
16367       # curr = lookup(curr->next)
16368       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16369       89/<- %ecx 0/r32/eax
16370       #
16371       eb/jump loop/disp8
16372     }
16373 $find-register:end:
16374     # . restore registers
16375     59/pop-to-ecx
16376     # . epilogue
16377     89/<- %esp 5/r32/ebp
16378     5d/pop-to-ebp
16379     c3/return
16380 
16381 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
16382     # . prologue
16383     55/push-ebp
16384     89/<- %ebp 4/r32/esp
16385     # . save registers
16386     51/push-ecx
16387     # var curr/ecx: (addr list stmt) = stmts
16388     8b/-> *(ebp+8) 1/r32/ecx
16389     {
16390       # if (curr == 0) break
16391       81 7/subop/compare %ecx 0/imm32
16392       74/jump-if-= break/disp8
16393       # if assigns-in-stmt?(curr->value, v) return true
16394       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16395       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
16396       3d/compare-eax-and 0/imm32/false
16397       75/jump-if-!= break/disp8
16398       # curr = lookup(curr->next)
16399       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16400       89/<- %ecx 0/r32/eax
16401       #
16402       eb/jump loop/disp8
16403     }
16404 $assigns-in-stmts?:end:
16405     # . restore registers
16406     59/pop-to-ecx
16407     # . epilogue
16408     89/<- %esp 5/r32/ebp
16409     5d/pop-to-ebp
16410     c3/return
16411 
16412 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
16413     # . prologue
16414     55/push-ebp
16415     89/<- %ebp 4/r32/esp
16416     # . save registers
16417     51/push-ecx
16418     # ecx = stmt
16419     8b/-> *(ebp+8) 1/r32/ecx
16420     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
16421     {
16422       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
16423       75/jump-if-!= break/disp8
16424       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16425       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
16426       eb/jump $assigns-in-stmt?:end/disp8
16427     }
16428     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
16429     {
16430       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
16431       75/jump-if-!= break/disp8
16432       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
16433       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
16434       eb/jump $assigns-in-stmt?:end/disp8
16435     }
16436     # otherwise return false
16437     b8/copy 0/imm32/false
16438 $assigns-in-stmt?:end:
16439     # . restore registers
16440     59/pop-to-ecx
16441     # . epilogue
16442     89/<- %esp 5/r32/ebp
16443     5d/pop-to-ebp
16444     c3/return
16445 
16446 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
16447     # . prologue
16448     55/push-ebp
16449     89/<- %ebp 4/r32/esp
16450     # . save registers
16451     51/push-ecx
16452     # var curr/ecx: (addr stmt-var) = stmt-var
16453     8b/-> *(ebp+8) 1/r32/ecx
16454     {
16455       # if (curr == 0) break
16456       81 7/subop/compare %ecx 0/imm32
16457       74/jump-if-= break/disp8
16458       # eax = lookup(curr->value)
16459       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
16460       # if (eax == v  &&  curr->is-deref? == false) return true
16461       {
16462         39/compare *(ebp+0xc) 0/r32/eax
16463         75/jump-if-!= break/disp8
16464         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
16465         75/jump-if-!= break/disp8
16466         b8/copy-to-eax 1/imm32/true
16467         eb/jump $assigns-in-stmt-vars?:end/disp8
16468       }
16469       # curr = lookup(curr->next)
16470       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
16471       89/<- %ecx 0/r32/eax
16472       #
16473       eb/jump loop/disp8
16474     }
16475 $assigns-in-stmt-vars?:end:
16476     # . restore registers
16477     59/pop-to-ecx
16478     # . epilogue
16479     89/<- %esp 5/r32/ebp
16480     5d/pop-to-ebp
16481     c3/return
16482 
16483 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
16484 # v is guaranteed to be within vars
16485 # 'start' is provided as an optimization, a pointer within vars
16486 # *start == v
16487 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
16488     # . prologue
16489     55/push-ebp
16490     89/<- %ebp 4/r32/esp
16491     # . save registers
16492     51/push-ecx
16493     52/push-edx
16494     53/push-ebx
16495     56/push-esi
16496     57/push-edi
16497     # ecx = v
16498     8b/-> *(ebp+8) 1/r32/ecx
16499     # var reg/edx: (addr array byte) = lookup(v->register)
16500     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
16501     89/<- %edx 0/r32/eax
16502     # var depth/ebx: int = v->block-depth
16503     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
16504     # var min/ecx: (addr handle var) = vars->data
16505     8b/-> *(ebp+0xc) 1/r32/ecx
16506     81 0/subop/add %ecx 8/imm32
16507     # TODO: check that start >= min and start < &vars->data[top]
16508     # TODO: check that *start == v
16509     # var curr/esi: (addr handle var) = start
16510     8b/-> *(ebp+0x10) 6/r32/esi
16511     # curr -= 8
16512     81 5/subop/subtract %esi 8/imm32
16513     {
16514 $same-register-spilled-before?:loop:
16515       # if (curr < min) break
16516       39/compare %esi 1/r32/ecx
16517       0f 82/jump-if-addr< break/disp32
16518       # var x/eax: (addr var) = lookup(*curr)
16519       (lookup *esi *(esi+4))  # => eax
16520       # if (x->block-depth < depth) break
16521       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
16522       0f 8c/jump-if-< break/disp32
16523       # if (x->register == 0) continue
16524       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
16525       74/jump-if-= $same-register-spilled-before?:continue/disp8
16526       # if (x->register == reg) return true
16527       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16528       (string-equal? %eax %edx)  # => eax
16529       3d/compare-eax-and 0/imm32/false
16530       b8/copy-to-eax 1/imm32/true
16531       75/jump-if-!= $same-register-spilled-before?:end/disp8
16532 $same-register-spilled-before?:continue:
16533       # curr -= 8
16534       81 5/subop/subtract %esi 8/imm32
16535       e9/jump loop/disp32
16536     }
16537 $same-register-spilled-before?:false:
16538     b8/copy-to-eax 0/imm32/false
16539 $same-register-spilled-before?:end:
16540     # . restore registers
16541     5f/pop-to-edi
16542     5e/pop-to-esi
16543     5b/pop-to-ebx
16544     5a/pop-to-edx
16545     59/pop-to-ecx
16546     # . epilogue
16547     89/<- %esp 5/r32/ebp
16548     5d/pop-to-ebp
16549     c3/return
16550 
16551 # Clean up global state for 'vars' until some block depth (inclusive).
16552 #
16553 # This would be a simple series of pops, if it wasn't for fn outputs, which
16554 # can occur anywhere in the stack.
16555 # So we have to _compact_ the entire array underlying the stack.
16556 #
16557 # We want to allow a fn output register to be written to by locals before the
16558 # output is set.
16559 # So fn outputs can't just be pushed at the start of the function.
16560 #
16561 # We want to allow other locals to shadow a fn output register after the
16562 # output is set.
16563 # So the output can't just always override anything in the stack. Sequence matters.
16564 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
16565     # pseudocode:
16566     #   to = vars->top  (which points outside the stack)
16567     #   while true
16568     #     if to <= 0
16569     #       break
16570     #     var v = vars->data[to-1]
16571     #     if v.depth < until and !in-function-outputs?(fn, v)
16572     #       break
16573     #     --to
16574     #   from = to
16575     #   while true
16576     #     if from >= vars->top
16577     #       break
16578     #     assert(from >= to)
16579     #     v = vars->data[from]
16580     #     if in-function-outputs?(fn, v)
16581     #       if from > to
16582     #         vars->data[to] = vars->data[from]
16583     #       ++to
16584     #     ++from
16585     #   vars->top = to
16586     #
16587     # . prologue
16588     55/push-ebp
16589     89/<- %ebp 4/r32/esp
16590     # . save registers
16591     50/push-eax
16592     52/push-edx
16593     53/push-ebx
16594     56/push-esi
16595     57/push-edi
16596     # ebx = vars
16597     8b/-> *(ebp+8) 3/r32/ebx
16598     # edx = until-block-depth
16599     8b/-> *(ebp+0xc) 2/r32/edx
16600 $clean-up-blocks:phase1:
16601     # var to/edi: int = vars->top
16602     8b/-> *ebx 7/r32/edi
16603     {
16604 $clean-up-blocks:loop1:
16605       # if (to <= 0) break
16606       81 7/subop/compare %edi 0/imm32
16607       7e/jump-if-<= break/disp8
16608       # var v/eax: (addr var) = lookup(vars->data[to-1]->var)
16609       8d/copy-address *(ebx+edi-4) 0/r32/eax  # vars + 8 + to - 12
16610       (lookup *eax *(eax+4))  # => eax
16611       # if (v->block-depth >= until-block-depth) continue
16612       39/compare *(eax+0x10) 2/r32/edx  # Var-block-depth
16613       {
16614         7d/jump-if->= break/disp8
16615         # if (!in-function-outputs?(fn, v)) break
16616         (in-function-outputs? *(ebp+0x10) %eax)  # => eax
16617         3d/compare-eax-and 0/imm32/false
16618         74/jump-if-= $clean-up-blocks:phase2/disp8
16619       }
16620 $clean-up-blocks:loop1-continue:
16621       # --to
16622       81 5/subop/subtract %edi 0xc/imm32
16623       #
16624       eb/jump loop/disp8
16625     }
16626 $clean-up-blocks:phase2:
16627     # var from/esi: int = to
16628     89/<- %esi 7/r32/edi
16629     {
16630 $clean-up-blocks:loop2:
16631       # if (from >= vars->top) break
16632       3b/compare 6/r32/esi *ebx
16633       7d/jump-if->= break/disp8
16634       # var v/eax: (addr var) = lookup(vars->data[from]->var)
16635       8d/copy-address *(ebx+esi+8) 0/r32/eax
16636       (lookup *eax *(eax+4))  # => eax
16637       # if !in-function-outputs?(fn, v) continue
16638       (in-function-outputs? *(ebp+0x10) %eax)  # => eax
16639       3d/compare-eax-and 0/imm32/false
16640       74/jump-if-= $clean-up-blocks:loop2-continue/disp8
16641       # invariant: from >= to
16642       # if (from > to) vars->data[to] = vars->data[from]
16643       {
16644         39/compare %esi 7/r32/edi
16645         7e/jump-if-<= break/disp8
16646         56/push-esi
16647         57/push-edi
16648         # . var from/esi: (addr byte) = &vars->data[from]
16649         8d/copy-address *(ebx+esi+8) 6/r32/esi
16650         # . var to/edi: (addr byte) = &vars->data[to]
16651         8d/copy-address *(ebx+edi+8) 7/r32/edi
16652         # .
16653         8b/-> *esi 0/r32/eax
16654         89/<- *edi 0/r32/eax
16655         8b/-> *(esi+4) 0/r32/eax
16656         89/<- *(edi+4) 0/r32/eax
16657         8b/-> *(esi+8) 0/r32/eax
16658         89/<- *(edi+8) 0/r32/eax
16659         5f/pop-to-edi
16660         5e/pop-to-esi
16661       }
16662       # ++to
16663       81 0/subop/add %edi 0xc/imm32
16664 $clean-up-blocks:loop2-continue:
16665       # ++from
16666       81 0/subop/add %esi 0xc/imm32
16667       #
16668       eb/jump loop/disp8
16669     }
16670     89/<- *ebx 7/r32/edi
16671 $clean-up-blocks:end:
16672     # . restore registers
16673     5f/pop-to-edi
16674     5e/pop-to-esi
16675     5b/pop-to-ebx
16676     5a/pop-to-edx
16677     58/pop-to-eax
16678     # . epilogue
16679     89/<- %esp 5/r32/ebp
16680     5d/pop-to-ebp
16681     c3/return
16682 
16683 in-function-outputs?:  # fn: (addr function), target: (addr var) -> result/eax: boolean
16684     # . prologue
16685     55/push-ebp
16686     89/<- %ebp 4/r32/esp
16687     # . save registers
16688     51/push-ecx
16689     # var curr/ecx: (addr list var) = lookup(fn->outputs)
16690     8b/-> *(ebp+8) 1/r32/ecx
16691     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
16692     89/<- %ecx 0/r32/eax
16693     # while curr != null
16694     {
16695       81 7/subop/compare %ecx 0/imm32
16696       74/jump-if-= break/disp8
16697       # var v/eax: (addr var) = lookup(curr->value)
16698       (lookup *ecx *(ecx+4))  # List-value List-value => eax
16699       # if (v == target) return true
16700       39/compare *(ebp+0xc) 0/r32/eax
16701       b8/copy-to-eax 1/imm32/true
16702       74/jump-if-= $in-function-outputs?:end/disp8
16703       # curr = curr->next
16704       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
16705       89/<- %ecx 0/r32/eax
16706       #
16707       eb/jump loop/disp8
16708     }
16709     b8/copy-to-eax 0/imm32
16710 $in-function-outputs?:end:
16711     # . restore registers
16712     59/pop-to-ecx
16713     # . epilogue
16714     89/<- %esp 5/r32/ebp
16715     5d/pop-to-ebp
16716     c3/return
16717 
16718 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
16719     # . prologue
16720     55/push-ebp
16721     89/<- %ebp 4/r32/esp
16722     # . save registers
16723     50/push-eax
16724     51/push-ecx
16725     52/push-edx
16726     # eax = stmt
16727     8b/-> *(ebp+0xc) 0/r32/eax
16728     # var v/ecx: (addr var)
16729     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
16730     89/<- %ecx 0/r32/eax
16731     # v->block-depth = *Curr-block-depth
16732     8b/-> *Curr-block-depth 0/r32/eax
16733     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
16734     # var n/edx: int = size-of(stmt->var)
16735     (size-of %ecx)  # => eax
16736     89/<- %edx 0/r32/eax
16737     # *Curr-local-stack-offset -= n
16738     29/subtract-from *Curr-local-stack-offset 2/r32/edx
16739     # v->offset = *Curr-local-stack-offset
16740     8b/-> *Curr-local-stack-offset 0/r32/eax
16741     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
16742     # if v is an array, do something special to initialize it
16743     {
16744       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16745       (is-mu-array? %eax)  # => eax
16746       3d/compare-eax-and 0/imm32/false
16747       0f 84/jump-if-= break/disp32
16748       # var array-size-without-size/edx: int = n-4
16749       81 5/subop/subtract %edx 4/imm32
16750       #
16751       (emit-array-data-initialization *(ebp+8) %edx)
16752       e9/jump $emit-subx-var-def:end/disp32
16753     }
16754     # another special-case for initializing streams
16755     # a stream is an array with 2 extra pointers
16756     {
16757       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
16758       (is-mu-stream? %eax)  # => eax
16759       3d/compare-eax-and 0/imm32/false
16760       0f 84/jump-if-= break/disp32
16761       # var array-size-without-size/edx: int = n-12
16762       81 5/subop/subtract %edx 0xc/imm32
16763       (emit-array-data-initialization *(ebp+8) %edx)
16764       # emit read and write pointers
16765       (emit-indent *(ebp+8) *Curr-block-depth)
16766       (write-buffered *(ebp+8) "68/push 0/imm32\n")
16767       (emit-indent *(ebp+8) *Curr-block-depth)
16768       (write-buffered *(ebp+8) "68/push 0/imm32\n")
16769       #
16770       eb/jump $emit-subx-var-def:end/disp8
16771     }
16772     # while n > 0
16773     {
16774       81 7/subop/compare %edx 0/imm32
16775       7e/jump-if-<= break/disp8
16776       (emit-indent *(ebp+8) *Curr-block-depth)
16777       (write-buffered *(ebp+8) "68/push 0/imm32\n")
16778       # n -= 4
16779       81 5/subop/subtract %edx 4/imm32
16780       #
16781       eb/jump loop/disp8
16782     }
16783 $emit-subx-var-def:end:
16784     # . restore registers
16785     5a/pop-to-edx
16786     59/pop-to-ecx
16787     58/pop-to-eax
16788     # . epilogue
16789     89/<- %esp 5/r32/ebp
16790     5d/pop-to-ebp
16791     c3/return
16792 
16793 emit-array-data-initialization:  # out: (addr buffered-file), n: int
16794     # . prologue
16795     55/push-ebp
16796     89/<- %ebp 4/r32/esp
16797     #
16798     (emit-indent *(ebp+8) *Curr-block-depth)
16799     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
16800     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
16801     (write-buffered *(ebp+8) ")\n")
16802     (emit-indent *(ebp+8) *Curr-block-depth)
16803     (write-buffered *(ebp+8) "68/push ")
16804     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
16805     (write-buffered *(ebp+8) "/imm32\n")
16806 $emit-array-data-initialization:end:
16807     # . epilogue
16808     89/<- %esp 5/r32/ebp
16809     5d/pop-to-ebp
16810     c3/return
16811 
16812 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
16813     # . prologue
16814     55/push-ebp
16815     89/<- %ebp 4/r32/esp
16816     # . save registers
16817     50/push-eax
16818     51/push-ecx
16819     # - some special-case primitives that don't actually use the 'primitives' data structure
16820     # var op/ecx: (addr array byte) = lookup(stmt->operation)
16821     8b/-> *(ebp+0xc) 1/r32/ecx
16822     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
16823     89/<- %ecx 0/r32/eax
16824     # array size
16825     {
16826       # if (!string-equal?(stmt->operation, "length")) break
16827       (string-equal? %ecx "length")  # => eax
16828       3d/compare-eax-and 0/imm32
16829       0f 84/jump-if-= break/disp32
16830       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16831       e9/jump $emit-subx-stmt:end/disp32
16832     }
16833     # index into array
16834     {
16835       # if (!string-equal?(stmt->operation, "index")) break
16836       (string-equal? %ecx "index")  # => eax
16837       3d/compare-eax-and 0/imm32
16838       0f 84/jump-if-= break/disp32
16839       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16840       e9/jump $emit-subx-stmt:end/disp32
16841     }
16842     # compute-offset for index into array
16843     {
16844       # if (!string-equal?(stmt->operation, "compute-offset")) break
16845       (string-equal? %ecx "compute-offset")  # => eax
16846       3d/compare-eax-and 0/imm32
16847       0f 84/jump-if-= break/disp32
16848       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16849       e9/jump $emit-subx-stmt:end/disp32
16850     }
16851     # get field from record
16852     {
16853       # if (!string-equal?(stmt->operation, "get")) break
16854       (string-equal? %ecx "get")  # => eax
16855       3d/compare-eax-and 0/imm32
16856       0f 84/jump-if-= break/disp32
16857       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
16858       e9/jump $emit-subx-stmt:end/disp32
16859     }
16860     # allocate scalar
16861     {
16862       # if (!string-equal?(stmt->operation, "allocate")) break
16863       (string-equal? %ecx "allocate")  # => eax
16864       3d/compare-eax-and 0/imm32
16865       0f 84/jump-if-= break/disp32
16866       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16867       e9/jump $emit-subx-stmt:end/disp32
16868     }
16869     # copy-object
16870     {
16871       # if (!string-equal?(stmt->operation, "copy-object")) break
16872       (string-equal? %ecx "copy-object")  # => eax
16873       3d/compare-eax-and 0/imm32
16874       0f 84/jump-if-= break/disp32
16875       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16876       e9/jump $emit-subx-stmt:end/disp32
16877     }
16878     # allocate array
16879     {
16880       # if (!string-equal?(stmt->operation, "populate")) break
16881       (string-equal? %ecx "populate")  # => eax
16882       3d/compare-eax-and 0/imm32
16883       0f 84/jump-if-= break/disp32
16884       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16885       e9/jump $emit-subx-stmt:end/disp32
16886     }
16887     # allocate stream
16888     {
16889       # if (!string-equal?(stmt->operation, "populate-stream")) break
16890       (string-equal? %ecx "populate-stream")  # => eax
16891       3d/compare-eax-and 0/imm32
16892       0f 84/jump-if-= break/disp32
16893       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16894       e9/jump $emit-subx-stmt:end/disp32
16895     }
16896     # read from stream
16897     {
16898       # if (!string-equal?(stmt->operation, "read-from-stream")) break
16899       (string-equal? %ecx "read-from-stream")  # => eax
16900       3d/compare-eax-and 0/imm32
16901       0f 84/jump-if-= break/disp32
16902       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16903       e9/jump $emit-subx-stmt:end/disp32
16904     }
16905     # write to stream
16906     {
16907       # if (!string-equal?(stmt->operation, "write-to-stream")) break
16908       (string-equal? %ecx "write-to-stream")  # => eax
16909       3d/compare-eax-and 0/imm32
16910       0f 84/jump-if-= break/disp32
16911       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
16912       e9/jump $emit-subx-stmt:end/disp32
16913     }
16914     # - if stmt matches a primitive, emit it
16915     {
16916 $emit-subx-stmt:check-for-primitive:
16917       # var curr/eax: (addr primitive)
16918       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
16919       3d/compare-eax-and 0/imm32
16920       74/jump-if-= break/disp8
16921 $emit-subx-stmt:primitive:
16922       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
16923       e9/jump $emit-subx-stmt:end/disp32
16924     }
16925     # - otherwise emit a call
16926     # TODO: type-checking
16927 $emit-subx-stmt:call:
16928     (emit-call *(ebp+8) *(ebp+0xc))
16929 $emit-subx-stmt:end:
16930     # . restore registers
16931     59/pop-to-ecx
16932     58/pop-to-eax
16933     # . epilogue
16934     89/<- %esp 5/r32/ebp
16935     5d/pop-to-ebp
16936     c3/return
16937 
16938 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
16939     # . prologue
16940     55/push-ebp
16941     89/<- %ebp 4/r32/esp
16942     # . save registers
16943     50/push-eax
16944     51/push-ecx
16945     52/push-edx
16946     53/push-ebx
16947     56/push-esi
16948     # esi = stmt
16949     8b/-> *(ebp+0xc) 6/r32/esi
16950     # var base/ebx: (addr var) = stmt->inouts[0]->value
16951     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
16952     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16953     89/<- %ebx 0/r32/eax
16954     # var elemsize/ecx: int = array-element-size(base)
16955     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
16956     89/<- %ecx 0/r32/eax
16957     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
16958     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
16959     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
16960     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
16961     89/<- %edx 0/r32/eax
16962     # if elemsize == 1
16963     {
16964       81 7/subop/compare %ecx 1/imm32
16965       75/jump-if-!= break/disp8
16966 $translate-mu-length-stmt:size-1:
16967       (emit-save-size-to *(ebp+8) %ebx %edx)
16968       e9/jump $translate-mu-length-stmt:end/disp32
16969     }
16970     # if elemsize is a power of 2 less than 256
16971     {
16972       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
16973       3d/compare-eax-and 0/imm32/false
16974       74/jump-if-= break/disp8
16975       81 7/subop/compare %ecx 0xff/imm32
16976       7f/jump-if-> break/disp8
16977 $translate-mu-length-stmt:size-power-of-2:
16978       (emit-save-size-to *(ebp+8) %ebx %edx)
16979       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
16980       e9/jump $translate-mu-length-stmt:end/disp32
16981     }
16982     # otherwise, the complex case
16983     # . emit register spills
16984     {
16985 $translate-mu-length-stmt:complex:
16986       (string-equal? %edx "eax")  # => eax
16987       3d/compare-eax-and 0/imm32/false
16988       75/break-if-!= break/disp8
16989       (emit-indent *(ebp+8) *Curr-block-depth)
16990       (write-buffered *(ebp+8) "50/push-eax\n")
16991     }
16992     {
16993       (string-equal? %edx "ecx")  # => eax
16994       3d/compare-eax-and 0/imm32/false
16995       75/break-if-!= break/disp8
16996       (emit-indent *(ebp+8) *Curr-block-depth)
16997       (write-buffered *(ebp+8) "51/push-ecx\n")
16998     }
16999     {
17000       (string-equal? %edx "edx")  # => eax
17001       3d/compare-eax-and 0/imm32/false
17002       75/break-if-!= break/disp8
17003       (emit-indent *(ebp+8) *Curr-block-depth)
17004       (write-buffered *(ebp+8) "52/push-edx\n")
17005     }
17006     # .
17007     (emit-save-size-to *(ebp+8) %ebx "eax")
17008     (emit-indent *(ebp+8) *Curr-block-depth)
17009     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
17010     (emit-indent *(ebp+8) *Curr-block-depth)
17011     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
17012     (write-int32-hex-buffered *(ebp+8) %ecx)
17013     (write-buffered *(ebp+8) "/imm32\n")
17014     (emit-indent *(ebp+8) *Curr-block-depth)
17015     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
17016     {
17017       (string-equal? %edx "eax")  # => eax
17018       3d/compare-eax-and 0/imm32/false
17019       75/break-if-!= break/disp8
17020       (emit-indent *(ebp+8) *Curr-block-depth)
17021       (write-buffered *(ebp+8) "89/<- %")
17022       (write-buffered *(ebp+8) %edx)
17023       (write-buffered *(ebp+8) " 0/r32/eax\n")
17024     }
17025     # . emit register restores
17026     {
17027       (string-equal? %edx "edx")  # => eax
17028       3d/compare-eax-and 0/imm32/false
17029       75/break-if-!= break/disp8
17030       (emit-indent *(ebp+8) *Curr-block-depth)
17031       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
17032     }
17033     {
17034       (string-equal? %edx "ecx")  # => eax
17035       3d/compare-eax-and 0/imm32/false
17036       75/break-if-!= break/disp8
17037       (emit-indent *(ebp+8) *Curr-block-depth)
17038       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
17039     }
17040     {
17041       (string-equal? %edx "eax")  # => eax
17042       3d/compare-eax-and 0/imm32/false
17043       75/break-if-!= break/disp8
17044       (emit-indent *(ebp+8) *Curr-block-depth)
17045       (write-buffered *(ebp+8) "58/pop-to-eax\n")
17046     }
17047 $translate-mu-length-stmt:end:
17048     # . restore registers
17049     5e/pop-to-esi
17050     5b/pop-to-ebx
17051     5a/pop-to-edx
17052     59/pop-to-ecx
17053     58/pop-to-eax
17054     # . epilogue
17055     89/<- %esp 5/r32/ebp
17056     5d/pop-to-ebp
17057     c3/return
17058 
17059 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17060     # . prologue
17061     55/push-ebp
17062     89/<- %ebp 4/r32/esp
17063     #
17064     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
17065     (size-of-type-id-as-array-element %eax)  # => eax
17066 $array-element-size:end:
17067     # . epilogue
17068     89/<- %esp 5/r32/ebp
17069     5d/pop-to-ebp
17070     c3/return
17071 
17072 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
17073     # precondition: n is positive
17074     # . prologue
17075     55/push-ebp
17076     89/<- %ebp 4/r32/esp
17077     #
17078     8b/-> *(ebp+8) 0/r32/eax
17079     # var t/eax: (addr type-tree)
17080     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17081     # if t == 0 abort
17082     3d/compare-eax-with 0/imm32
17083     0f 84/jump-if-== $array-element-type-id:error0/disp32
17084     # if t->is-atom? abort
17085     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17086     0f 85/jump-if-!= $array-element-type-id:error1/disp32
17087     # if (t->left == addr) t = t->right
17088     {
17089       50/push-eax
17090       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17091       (is-simple-mu-type? %eax 2)  # addr => eax
17092       3d/compare-eax-with 0/imm32/false
17093       58/pop-to-eax
17094       74/jump-if-= break/disp8
17095 $array-element-type-id:skip-addr:
17096       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17097     }
17098     # if t == 0 abort
17099     3d/compare-eax-with 0/imm32
17100     0f 84/jump-if-= $array-element-type-id:error2/disp32
17101     # if t->is-atom? abort
17102     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17103     0f 85/jump-if-!= $array-element-type-id:error2/disp32
17104     # if t->left != array abort
17105     {
17106       50/push-eax
17107       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17108       (is-simple-mu-type? %eax 3)  # array => eax
17109       3d/compare-eax-with 0/imm32/false
17110       58/pop-to-eax
17111 $array-element-type-id:no-array:
17112       0f 84/jump-if-= $array-element-type-id:error2/disp32
17113     }
17114 $array-element-type-id:skip-array:
17115     # t = t->right
17116     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17117     # if t == 0 abort
17118     3d/compare-eax-with 0/imm32
17119     0f 84/jump-if-= $array-element-type-id:error2/disp32
17120     # if t->is-atom? abort
17121     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17122     0f 85/jump-if-!= $array-element-type-id:error2/disp32
17123     # return t->left->value
17124     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17125     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
17126 $array-element-type-id:end:
17127     # . epilogue
17128     89/<- %esp 5/r32/ebp
17129     5d/pop-to-ebp
17130     c3/return
17131 
17132 $array-element-type-id:error0:
17133     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
17134     50/push-eax
17135     8b/-> *(ebp+8) 0/r32/eax
17136     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17137     (write-buffered *(ebp+0xc) %eax)
17138     58/pop-to-eax
17139     (write-buffered *(ebp+0xc) "' has no type\n")
17140     (flush *(ebp+0xc))
17141     (stop *(ebp+0x10) 1)
17142     # never gets here
17143 
17144 $array-element-type-id:error1:
17145     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
17146     50/push-eax
17147     8b/-> *(ebp+8) 0/r32/eax
17148     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17149     (write-buffered *(ebp+0xc) %eax)
17150     58/pop-to-eax
17151     (write-buffered *(ebp+0xc) "' has atomic type ")
17152     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
17153     (write-buffered *(ebp+0xc) Newline)
17154     (flush *(ebp+0xc))
17155     (stop *(ebp+0x10) 1)
17156     # never gets here
17157 
17158 $array-element-type-id:error2:
17159     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
17160     50/push-eax
17161     8b/-> *(ebp+8) 0/r32/eax
17162     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17163     (write-buffered *(ebp+0xc) %eax)
17164     58/pop-to-eax
17165     (write-buffered *(ebp+0xc) "' has non-array type\n")
17166     (flush *(ebp+0xc))
17167     (stop *(ebp+0x10) 1)
17168     # never gets here
17169 
17170 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
17171     # . prologue
17172     55/push-ebp
17173     89/<- %ebp 4/r32/esp
17174     # eax = t
17175     8b/-> *(ebp+8) 0/r32/eax
17176     # if t is 'byte', size is 1
17177     3d/compare-eax-and 8/imm32/byte
17178     {
17179       75/jump-if-!= break/disp8
17180       b8/copy-to-eax 1/imm32
17181       eb/jump $size-of-type-id-as-array-element:end/disp8
17182     }
17183     # otherwise proceed as usual
17184     (size-of-type-id %eax)  # => eax
17185 $size-of-type-id-as-array-element:end:
17186     # . epilogue
17187     89/<- %esp 5/r32/ebp
17188     5d/pop-to-ebp
17189     c3/return
17190 
17191 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
17192     # . prologue
17193     55/push-ebp
17194     89/<- %ebp 4/r32/esp
17195     # . save registers
17196     50/push-eax
17197     53/push-ebx
17198     # ebx = base
17199     8b/-> *(ebp+0xc) 3/r32/ebx
17200     (emit-indent *(ebp+8) *Curr-block-depth)
17201     (write-buffered *(ebp+8) "8b/-> *")
17202     # if base is an (addr array ...) in a register
17203     {
17204       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
17205       74/jump-if-= break/disp8
17206 $emit-save-size-to:emit-base-from-register:
17207       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
17208       (write-buffered *(ebp+8) %eax)
17209       eb/jump $emit-save-size-to:emit-output/disp8
17210     }
17211     # otherwise if base is an (array ...) on the stack
17212     {
17213       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
17214       74/jump-if-= break/disp8
17215 $emit-save-size-to:emit-base-from-stack:
17216       (write-buffered *(ebp+8) "(ebp+")
17217       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
17218       (write-buffered *(ebp+8) ")")
17219     }
17220 $emit-save-size-to:emit-output:
17221     (write-buffered *(ebp+8) " ")
17222     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
17223     (write-int32-hex-buffered *(ebp+8) *eax)
17224     (write-buffered *(ebp+8) "/r32\n")
17225 $emit-save-size-to:end:
17226     # . restore registers
17227     5b/pop-to-ebx
17228     58/pop-to-eax
17229     # . epilogue
17230     89/<- %esp 5/r32/ebp
17231     5d/pop-to-ebp
17232     c3/return
17233 
17234 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
17235     # . prologue
17236     55/push-ebp
17237     89/<- %ebp 4/r32/esp
17238     # . save registers
17239     50/push-eax
17240     #
17241     (emit-indent *(ebp+8) *Curr-block-depth)
17242     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
17243     (write-buffered *(ebp+8) *(ebp+0xc))
17244     (write-buffered *(ebp+8) Space)
17245     (num-shift-rights *(ebp+0x10))  # => eax
17246     (write-int32-hex-buffered *(ebp+8) %eax)
17247     (write-buffered *(ebp+8) "/imm8\n")
17248 $emit-divide-by-shift-right:end:
17249     # . restore registers
17250     58/pop-to-eax
17251     # . epilogue
17252     89/<- %esp 5/r32/ebp
17253     5d/pop-to-ebp
17254     c3/return
17255 
17256 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17257     # . prologue
17258     55/push-ebp
17259     89/<- %ebp 4/r32/esp
17260     # . save registers
17261     51/push-ecx
17262     # ecx = stmt
17263     8b/-> *(ebp+0xc) 1/r32/ecx
17264     # var base/ecx: (addr var) = stmt->inouts[0]
17265     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17266     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17267     89/<- %ecx 0/r32/eax
17268     # if (var->register) do one thing
17269     {
17270       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
17271       74/jump-if-= break/disp8
17272       # TODO: ensure there's no dereference
17273       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
17274       eb/jump $translate-mu-index-stmt:end/disp8
17275     }
17276     # if (var->offset) do a different thing
17277     {
17278       81 7/subop/compare *(ecx+0x14) 0/imm32  # Var-offset
17279       74/jump-if-= break/disp8
17280       # TODO: ensure there's no dereference
17281       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
17282       eb/jump $translate-mu-index-stmt:end/disp8
17283     }
17284 $translate-mu-index-stmt:end:
17285     # . restore registers
17286     59/pop-to-ecx
17287     # . epilogue
17288     89/<- %esp 5/r32/ebp
17289     5d/pop-to-ebp
17290     c3/return
17291 
17292 $translate-mu-index-stmt-with-array:error1:
17293     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
17294     (flush *(ebp+0x10))
17295     (stop *(ebp+0x14) 1)
17296     # never gets here
17297 
17298 $translate-mu-index-stmt-with-array:error2:
17299     (write-buffered *(ebp+0x10) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
17300     (flush *(ebp+0x10))
17301     (stop *(ebp+0x14) 1)
17302     # never gets here
17303 
17304 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17305     # . prologue
17306     55/push-ebp
17307     89/<- %ebp 4/r32/esp
17308     # . save registers
17309     50/push-eax
17310     51/push-ecx
17311     52/push-edx
17312     53/push-ebx
17313     #
17314     (emit-indent *(ebp+8) *Curr-block-depth)
17315     (write-buffered *(ebp+8) "8d/copy-address *(")
17316     # TODO: ensure inouts[0] is in a register and not dereferenced
17317 $translate-mu-index-stmt-with-array-in-register:emit-base:
17318     # ecx = stmt
17319     8b/-> *(ebp+0xc) 1/r32/ecx
17320     # var base/ebx: (addr var) = inouts[0]
17321     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17322     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17323     89/<- %ebx 0/r32/eax
17324     # print base->register " + "
17325     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
17326     (write-buffered *(ebp+8) %eax)
17327     (write-buffered *(ebp+8) " + ")
17328     # var index/edx: (addr var) = inouts[1]
17329     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17330     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17331     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17332     89/<- %edx 0/r32/eax
17333     # if index->register
17334     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
17335     {
17336       0f 84/jump-if-= break/disp32
17337 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
17338       # if index is an int
17339       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17340       (is-simple-mu-type? %eax 1)  # int => eax
17341       3d/compare-eax-and 0/imm32/false
17342       {
17343         0f 84/jump-if-= break/disp32
17344 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
17345         # print index->register "<<" log2(array-element-size(base)) " + 4) "
17346         # . index->register "<<"
17347         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17348         (write-buffered *(ebp+8) %eax)
17349         (write-buffered *(ebp+8) "<<")
17350         # . log2(array-element-size(base->type))
17351         # TODO: ensure size is a power of 2
17352         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
17353         (num-shift-rights %eax)  # => eax
17354         (write-int32-hex-buffered *(ebp+8) %eax)
17355         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
17356       }
17357       # if index->type is any other atom, abort
17358       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17359       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17360       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
17361       # if index has type (offset ...)
17362       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17363       (is-simple-mu-type? %eax 7)  # => eax
17364       3d/compare-eax-and 0/imm32/false
17365       {
17366         0f 84/jump-if-= break/disp32
17367         # print index->register
17368 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
17369         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17370         (write-buffered *(ebp+8) %eax)
17371       }
17372 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
17373       (write-buffered *(ebp+8) " + 4) ")
17374       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
17375     }
17376     # otherwise if index is a literal
17377     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17378     (is-simple-mu-type? %eax 0)  # => eax
17379     3d/compare-eax-and 0/imm32/false
17380     {
17381       0f 84/jump-if-= break/disp32
17382 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
17383       # var index-value/edx: int = parse-hex-int(index->name)
17384       (lookup *edx *(edx+4))  # Var-name Var-name => eax
17385       (parse-hex-int %eax)  # => eax
17386       89/<- %edx 0/r32/eax
17387       # offset = idx-value * array-element-size(base->type)
17388       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
17389       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
17390       # offset += 4 for array size
17391       05/add-to-eax 4/imm32
17392       # TODO: check edx for overflow
17393       # print offset
17394       (write-int32-hex-buffered *(ebp+8) %eax)
17395       (write-buffered *(ebp+8) ") ")
17396       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
17397     }
17398     # otherwise abort
17399     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
17400 $translate-mu-index-stmt-with-array-in-register:emit-output:
17401     # outputs[0] "/r32"
17402     8b/-> *(ebp+0xc) 1/r32/ecx
17403     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17404     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17405     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17406     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
17407     (write-int32-hex-buffered *(ebp+8) *eax)
17408     (write-buffered *(ebp+8) "/r32\n")
17409 $translate-mu-index-stmt-with-array-in-register:end:
17410     # . restore registers
17411     5b/pop-to-ebx
17412     5a/pop-to-edx
17413     59/pop-to-ecx
17414     58/pop-to-eax
17415     # . epilogue
17416     89/<- %esp 5/r32/ebp
17417     5d/pop-to-ebp
17418     c3/return
17419 
17420 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17421     # . prologue
17422     55/push-ebp
17423     89/<- %ebp 4/r32/esp
17424     # . save registers
17425     50/push-eax
17426     51/push-ecx
17427     52/push-edx
17428     53/push-ebx
17429     #
17430     (emit-indent *(ebp+8) *Curr-block-depth)
17431     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
17432     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
17433     8b/-> *(ebp+0xc) 0/r32/eax
17434     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17435     89/<- %edx 0/r32/eax
17436     # var base/ecx: (addr var) = lookup(curr->value)
17437     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17438     89/<- %ecx 0/r32/eax
17439     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
17440     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
17441     # var index/edx: (handle var) = curr2->value
17442     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17443     89/<- %edx 0/r32/eax
17444     # if index->register
17445     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
17446     {
17447       0f 84/jump-if-= break/disp32
17448 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
17449       # if index is an int
17450       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17451       (is-simple-mu-type? %eax 1)  # int => eax
17452       3d/compare-eax-and 0/imm32/false
17453       {
17454         0f 84/jump-if-= break/disp32
17455 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
17456         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
17457         # . inouts[1]->register "<<"
17458         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17459         (write-buffered *(ebp+8) %eax)
17460         (write-buffered *(ebp+8) "<<")
17461         # . log2(array-element-size(base))
17462         # TODO: ensure size is a power of 2
17463         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
17464         (num-shift-rights %eax)  # => eax
17465         (write-int32-hex-buffered *(ebp+8) %eax)
17466         #
17467         (write-buffered *(ebp+8) " + ")
17468         #
17469         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
17470         05/add-to-eax 4/imm32  # for array length
17471         (write-int32-hex-buffered *(ebp+8) %eax)
17472         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
17473       }
17474       # if index->type is any other atom, abort
17475       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17476       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
17477       0f 85/jump-if-!= $translate-mu-index-stmt-with-array:error2/disp32
17478       # if index has type (offset ...)
17479       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17480       (is-simple-mu-type? %eax 7)  # => eax
17481       3d/compare-eax-and 0/imm32/false
17482       {
17483         0f 84/jump-if-= break/disp32
17484         # print index->register
17485 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
17486         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
17487         (write-buffered *(ebp+8) %eax)
17488       }
17489 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
17490       (write-buffered *(ebp+8) ") ")
17491       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
17492     }
17493     # otherwise if index is a literal
17494     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
17495     (is-simple-mu-type? %eax 0)  # => eax
17496     3d/compare-eax-and 0/imm32/false
17497     {
17498       0f 84/jump-if-= break/disp32
17499 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
17500       # var idx-value/edx: int = parse-hex-int(index->name)
17501       (lookup *edx *(edx+4))  # Var-name Var-name => eax
17502       (parse-hex-int %eax)  # Var-name => eax
17503       89/<- %edx 0/r32/eax
17504       # offset = idx-value * array-element-size(base)
17505       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
17506       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
17507       # offset += base->offset
17508       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
17509       # offset += 4 for array size
17510       05/add-to-eax 4/imm32
17511       # TODO: check edx for overflow
17512       # print offset
17513       (write-int32-hex-buffered *(ebp+8) %eax)
17514       (write-buffered *(ebp+8) ") ")
17515       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
17516     }
17517     # otherwise abort
17518     e9/jump $translate-mu-index-stmt-with-array:error1/disp32
17519 $translate-mu-index-stmt-with-array-on-stack:emit-output:
17520     # outputs[0] "/r32"
17521     8b/-> *(ebp+0xc) 0/r32/eax
17522     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17523     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17524     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17525     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
17526     (write-int32-hex-buffered *(ebp+8) *eax)
17527     (write-buffered *(ebp+8) "/r32\n")
17528 $translate-mu-index-stmt-with-array-on-stack:end:
17529     # . restore registers
17530     5b/pop-to-ebx
17531     5a/pop-to-edx
17532     59/pop-to-ecx
17533     58/pop-to-eax
17534     # . epilogue
17535     89/<- %esp 5/r32/ebp
17536     5d/pop-to-ebp
17537     c3/return
17538 
17539 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17540     # . prologue
17541     55/push-ebp
17542     89/<- %ebp 4/r32/esp
17543     # . save registers
17544     50/push-eax
17545     51/push-ecx
17546     52/push-edx
17547     53/push-ebx
17548     #
17549     (emit-indent *(ebp+8) *Curr-block-depth)
17550     (write-buffered *(ebp+8) "69/multiply")
17551     # ecx = stmt
17552     8b/-> *(ebp+0xc) 1/r32/ecx
17553     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
17554     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17555     89/<- %ebx 0/r32/eax
17556 $translate-mu-compute-index-stmt:emit-index:
17557     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
17558     (emit-subx-var-as-rm32 *(ebp+8) %eax)
17559     (write-buffered *(ebp+8) Space)
17560 $translate-mu-compute-index-stmt:emit-elem-size:
17561     # var base/ebx: (addr var)
17562     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
17563     89/<- %ebx 0/r32/eax
17564     # print array-element-size(base)
17565     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
17566     (write-int32-hex-buffered *(ebp+8) %eax)
17567     (write-buffered *(ebp+8) "/imm32 ")
17568 $translate-mu-compute-index-stmt:emit-output:
17569     # outputs[0] "/r32"
17570     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17571     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17572     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17573     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
17574     (write-int32-hex-buffered *(ebp+8) *eax)
17575     (write-buffered *(ebp+8) "/r32\n")
17576 $translate-mu-compute-index-stmt:end:
17577     # . restore registers
17578     5b/pop-to-ebx
17579     5a/pop-to-edx
17580     59/pop-to-ecx
17581     58/pop-to-eax
17582     # . epilogue
17583     89/<- %esp 5/r32/ebp
17584     5d/pop-to-ebp
17585     c3/return
17586 
17587 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
17588     # . prologue
17589     55/push-ebp
17590     89/<- %ebp 4/r32/esp
17591     # . save registers
17592     50/push-eax
17593     51/push-ecx
17594     52/push-edx
17595     #
17596     (emit-indent *(ebp+8) *Curr-block-depth)
17597     (write-buffered *(ebp+8) "8d/copy-address ")
17598     # ecx = stmt
17599     8b/-> *(ebp+0xc) 1/r32/ecx
17600     # var offset/edx: int = get offset of stmt
17601     (mu-get-offset %ecx)  # => eax
17602     89/<- %edx 0/r32/eax
17603     # var base/eax: (addr var) = stmt->inouts->value
17604     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17605     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17606     # if base is in a register
17607     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
17608     {
17609       0f 84/jump-if-= break/disp32
17610 $translate-mu-get-stmt:emit-register-input:
17611       # emit "*(" base->register " + " offset ") "
17612       (write-buffered *(ebp+8) "*(")
17613       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17614       (write-buffered *(ebp+8) %eax)
17615       (write-buffered *(ebp+8) " + ")
17616       (write-int32-hex-buffered *(ebp+8) %edx)
17617       (write-buffered *(ebp+8) ") ")
17618       e9/jump $translate-mu-get-stmt:emit-output/disp32
17619     }
17620     # otherwise base is on the stack
17621     {
17622 $translate-mu-get-stmt:emit-stack-input:
17623       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
17624       (write-buffered *(ebp+8) "*(ebp+")
17625       03/add *(eax+0x14) 2/r32/edx  # Var-offset
17626       (write-int32-hex-buffered *(ebp+8) %edx)
17627       (write-buffered *(ebp+8) ") ")
17628       eb/jump $translate-mu-get-stmt:emit-output/disp8
17629     }
17630 $translate-mu-get-stmt:emit-output:
17631     # var output/eax: (addr var) = stmt->outputs->value
17632     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
17633     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17634     # emit offset->register "/r32"
17635     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17636     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
17637     (write-int32-hex-buffered *(ebp+8) *eax)
17638     (write-buffered *(ebp+8) "/r32\n")
17639 $translate-mu-get-stmt:end:
17640     # . restore registers
17641     5a/pop-to-edx
17642     59/pop-to-ecx
17643     58/pop-to-eax
17644     # . epilogue
17645     89/<- %esp 5/r32/ebp
17646     5d/pop-to-ebp
17647     c3/return
17648 
17649 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17650     # . prologue
17651     55/push-ebp
17652     89/<- %ebp 4/r32/esp
17653     # . save registers
17654     50/push-eax
17655     #
17656     (emit-indent *(ebp+8) *Curr-block-depth)
17657     (write-buffered *(ebp+8) "(copy-bytes")
17658     # eax = stmt
17659     8b/-> *(ebp+0xc) 0/r32/eax
17660     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
17661     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17662     (emit-subx-call-operand *(ebp+8) %eax)
17663     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
17664     (emit-subx-call-operand *(ebp+8) %eax)
17665     (write-buffered *(ebp+8) Space)
17666     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
17667     (write-int32-hex-buffered *(ebp+8) %eax)
17668     (write-buffered *(ebp+8) ")\n")
17669 $translate-mu-copy-object-stmt:end:
17670     # . restore registers
17671     58/pop-to-eax
17672     # . epilogue
17673     89/<- %esp 5/r32/ebp
17674     5d/pop-to-ebp
17675     c3/return
17676 
17677 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17678     # . prologue
17679     55/push-ebp
17680     89/<- %ebp 4/r32/esp
17681     # . save registers
17682     50/push-eax
17683     56/push-esi
17684     57/push-edi
17685     # esi = stmt
17686     8b/-> *(ebp+0xc) 6/r32/esi
17687     # var target/edi: (addr stmt-var) = stmt->inouts[0]
17688     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17689     89/<- %edi 0/r32/eax
17690     #
17691     (emit-indent *(ebp+8) *Curr-block-depth)
17692     (write-buffered *(ebp+8) "(allocate Heap ")
17693     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
17694     (write-int32-hex-buffered *(ebp+8) %eax)
17695     (emit-subx-call-operand *(ebp+8) %edi)
17696     (write-buffered *(ebp+8) ")\n")
17697 $translate-mu-allocate-stmt:end:
17698     # . restore registers
17699     5f/pop-to-edi
17700     5e/pop-to-esi
17701     58/pop-to-eax
17702     # . epilogue
17703     89/<- %esp 5/r32/ebp
17704     5d/pop-to-ebp
17705     c3/return
17706 
17707 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17708     # . prologue
17709     55/push-ebp
17710     89/<- %ebp 4/r32/esp
17711     # var t/eax: (addr type-tree) = s->value->type
17712     8b/-> *(ebp+8) 0/r32/eax
17713     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17714     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17715     # TODO: check eax != 0
17716     # TODO: check !t->is-atom?
17717     # TODO: check t->left == addr
17718     # t = t->right
17719 $addr-handle-payload-size:skip-addr:
17720     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17721     # TODO: check eax != 0
17722     # TODO: check !t->is-atom?
17723     # TODO: check t->left == handle
17724     # t = t->right
17725 $addr-handle-payload-size:skip-handle:
17726     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17727     # TODO: check eax != 0
17728     # if !t->is-atom? t = t->left
17729     81 7/subop/compare *eax 0/imm32/false
17730     {
17731       75/jump-if-!= break/disp8
17732       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17733     }
17734     # TODO: check t->is-atom?
17735     # return size(t->value)
17736     (size-of-type-id *(eax+4))  # Type-tree-value => eax
17737 $addr-handle-payload-size:end:
17738     # . epilogue
17739     89/<- %esp 5/r32/ebp
17740     5d/pop-to-ebp
17741     c3/return
17742 
17743 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17744     # . prologue
17745     55/push-ebp
17746     89/<- %ebp 4/r32/esp
17747     # var t/eax: (addr type-tree) = s->value->type
17748     8b/-> *(ebp+8) 0/r32/eax
17749     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17750     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17751     # TODO: check eax != 0
17752     # TODO: check !t->is-atom?
17753     # TODO: check t->left == addr
17754     # t = t->right
17755 $addr-payload-size:skip-addr:
17756     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17757     # TODO: check eax != 0
17758     # if !t->is-atom? t = t->left
17759     81 7/subop/compare *eax 0/imm32/false
17760     {
17761       75/jump-if-!= break/disp8
17762       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17763     }
17764     # TODO: check t->is-atom?
17765     # return size(t->value)
17766     (size-of-type-id *(eax+4))  # Type-tree-value => eax
17767 $addr-payload-size:end:
17768     # . epilogue
17769     89/<- %esp 5/r32/ebp
17770     5d/pop-to-ebp
17771     c3/return
17772 
17773 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17774     # . prologue
17775     55/push-ebp
17776     89/<- %ebp 4/r32/esp
17777     # . save registers
17778     50/push-eax
17779     51/push-ecx
17780     56/push-esi
17781     57/push-edi
17782     # esi = stmt
17783     8b/-> *(ebp+0xc) 6/r32/esi
17784     # var target/edi: (addr stmt-var) = stmt->inouts[0]
17785     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17786     89/<- %edi 0/r32/eax
17787     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
17788     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
17789     89/<- %ecx 0/r32/eax
17790     #
17791     (emit-indent *(ebp+8) *Curr-block-depth)
17792     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
17793     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
17794     (write-int32-hex-buffered *(ebp+8) %eax)
17795     (emit-subx-call-operand *(ebp+8) %ecx)
17796     (emit-subx-call-operand *(ebp+8) %edi)
17797     (write-buffered *(ebp+8) ")\n")
17798 $translate-mu-populate-stmt:end:
17799     # . restore registers
17800     5f/pop-to-edi
17801     5e/pop-to-esi
17802     59/pop-to-ecx
17803     58/pop-to-eax
17804     # . epilogue
17805     89/<- %esp 5/r32/ebp
17806     5d/pop-to-ebp
17807     c3/return
17808 
17809 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17810     # . prologue
17811     55/push-ebp
17812     89/<- %ebp 4/r32/esp
17813     # . save registers
17814     50/push-eax
17815     51/push-ecx
17816     56/push-esi
17817     57/push-edi
17818     # esi = stmt
17819     8b/-> *(ebp+0xc) 6/r32/esi
17820     # var target/edi: (addr stmt-var) = stmt->inouts[0]
17821     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17822     89/<- %edi 0/r32/eax
17823     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
17824     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
17825     89/<- %ecx 0/r32/eax
17826     #
17827     (emit-indent *(ebp+8) *Curr-block-depth)
17828     (write-buffered *(ebp+8) "(new-stream Heap ")
17829     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
17830     (write-int32-hex-buffered *(ebp+8) %eax)
17831     (emit-subx-call-operand *(ebp+8) %ecx)
17832     (emit-subx-call-operand *(ebp+8) %edi)
17833     (write-buffered *(ebp+8) ")\n")
17834 $translate-mu-populate-stream-stmt:end:
17835     # . restore registers
17836     5f/pop-to-edi
17837     5e/pop-to-esi
17838     59/pop-to-ecx
17839     58/pop-to-eax
17840     # . epilogue
17841     89/<- %esp 5/r32/ebp
17842     5d/pop-to-ebp
17843     c3/return
17844 
17845 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17846     # . prologue
17847     55/push-ebp
17848     89/<- %ebp 4/r32/esp
17849     # . save registers
17850     50/push-eax
17851     51/push-ecx
17852     56/push-esi
17853     57/push-edi
17854     # esi = stmt
17855     8b/-> *(ebp+0xc) 6/r32/esi
17856     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
17857     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17858     89/<- %ecx 0/r32/eax
17859     # var target/edi: (addr stmt-var) = stmt->inouts[1]
17860     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
17861     89/<- %edi 0/r32/eax
17862     #
17863     (emit-indent *(ebp+8) *Curr-block-depth)
17864     (write-buffered *(ebp+8) "(read-from-stream")
17865     (emit-subx-call-operand *(ebp+8) %ecx)
17866     (emit-subx-call-operand *(ebp+8) %edi)
17867     (write-buffered *(ebp+8) Space)
17868     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
17869     (write-int32-hex-buffered *(ebp+8) %eax)
17870     (write-buffered *(ebp+8) ")\n")
17871 $translate-mu-read-from-stream-stmt:end:
17872     # . restore registers
17873     5f/pop-to-edi
17874     5e/pop-to-esi
17875     59/pop-to-ecx
17876     58/pop-to-eax
17877     # . epilogue
17878     89/<- %esp 5/r32/ebp
17879     5d/pop-to-ebp
17880     c3/return
17881 
17882 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17883     # . prologue
17884     55/push-ebp
17885     89/<- %ebp 4/r32/esp
17886     # . save registers
17887     50/push-eax
17888     51/push-ecx
17889     56/push-esi
17890     57/push-edi
17891     # esi = stmt
17892     8b/-> *(ebp+0xc) 6/r32/esi
17893     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
17894     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17895     89/<- %ecx 0/r32/eax
17896     # var target/edi: (addr stmt-var) = stmt->inouts[1]
17897     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
17898     89/<- %edi 0/r32/eax
17899     #
17900     (emit-indent *(ebp+8) *Curr-block-depth)
17901     (write-buffered *(ebp+8) "(write-to-stream")
17902     (emit-subx-call-operand *(ebp+8) %ecx)
17903     (flush *(ebp+8))
17904     (emit-subx-call-operand *(ebp+8) %edi)
17905     (flush *(ebp+8))
17906     (write-buffered *(ebp+8) Space)
17907     (flush *(ebp+8))
17908     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
17909     (write-int32-hex-buffered *(ebp+8) %eax)
17910     (write-buffered *(ebp+8) ")\n")
17911 $translate-mu-write-to-stream-stmt:end:
17912     # . restore registers
17913     5f/pop-to-edi
17914     5e/pop-to-esi
17915     59/pop-to-ecx
17916     58/pop-to-eax
17917     # . epilogue
17918     89/<- %esp 5/r32/ebp
17919     5d/pop-to-ebp
17920     c3/return
17921 
17922 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17923     # . prologue
17924     55/push-ebp
17925     89/<- %ebp 4/r32/esp
17926     # var t/eax: (addr type-tree) = s->value->type
17927     8b/-> *(ebp+8) 0/r32/eax
17928     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17929     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17930     # TODO: check eax != 0
17931     # TODO: check !t->is-atom?
17932     # TODO: check t->left == addr
17933     # t = t->right
17934 $addr-handle-array-payload-size:skip-addr:
17935     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17936     # TODO: check eax != 0
17937     # TODO: check !t->is-atom?
17938     # TODO: check t->left == handle
17939     # t = t->right
17940 $addr-handle-array-payload-size:skip-handle:
17941     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17942     # TODO: check eax != 0
17943     # TODO: check !t->is-atom?
17944     # TODO: check t->left == array
17945     # t = t->right
17946 $addr-handle-array-payload-size:skip-array:
17947     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17948     # TODO: check eax != 0
17949     # if !t->is-atom? t = t->left
17950     81 7/subop/compare *eax 0/imm32/false
17951     {
17952       75/jump-if-!= break/disp8
17953       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17954     }
17955 $addr-handle-array-payload-size:compute-size:
17956     # TODO: check t->is-atom?
17957     # return size(t->value)
17958     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
17959 $addr-handle-array-payload-size:end:
17960     # . epilogue
17961     89/<- %esp 5/r32/ebp
17962     5d/pop-to-ebp
17963     c3/return
17964 
17965 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
17966     # . prologue
17967     55/push-ebp
17968     89/<- %ebp 4/r32/esp
17969     # var t/eax: (addr type-tree) = s->value->type
17970     8b/-> *(ebp+8) 0/r32/eax
17971     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17972     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17973     # TODO: check eax != 0
17974     # TODO: check !t->is-atom?
17975     # TODO: check t->left == addr
17976     # t = t->right
17977 $addr-handle-stream-payload-size:skip-addr:
17978     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17979     # TODO: check eax != 0
17980     # TODO: check !t->is-atom?
17981     # TODO: check t->left == handle
17982     # t = t->right
17983 $addr-handle-stream-payload-size:skip-handle:
17984     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17985     # TODO: check eax != 0
17986     # TODO: check !t->is-atom?
17987     # TODO: check t->left == stream
17988     # t = t->right
17989 $addr-handle-stream-payload-size:skip-stream:
17990     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
17991     # TODO: check eax != 0
17992     # if !t->is-atom? t = t->left
17993     81 7/subop/compare *eax 0/imm32/false
17994     {
17995       75/jump-if-!= break/disp8
17996       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
17997     }
17998 $addr-handle-stream-payload-size:compute-size:
17999     # TODO: check t->is-atom?
18000     # return size(t->value)
18001     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
18002 $addr-handle-stream-payload-size:end:
18003     # . epilogue
18004     89/<- %esp 5/r32/ebp
18005     5d/pop-to-ebp
18006     c3/return
18007 
18008 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
18009     # precondition: n is positive
18010     # . prologue
18011     55/push-ebp
18012     89/<- %ebp 4/r32/esp
18013     # eax = n
18014     8b/-> *(ebp+8) 0/r32/eax
18015     # if (n < 0) abort
18016     3d/compare-eax-with 0/imm32
18017     0f 8c/jump-if-< $power-of-2?:abort/disp32
18018     # var tmp/eax: int = n-1
18019     48/decrement-eax
18020     # var tmp2/eax: int = n & tmp
18021     23/and-> *(ebp+8) 0/r32/eax
18022     # return (tmp2 == 0)
18023     3d/compare-eax-and 0/imm32
18024     0f 94/set-byte-if-= %al
18025     81 4/subop/and %eax 0xff/imm32
18026 $power-of-2?:end:
18027     # . epilogue
18028     89/<- %esp 5/r32/ebp
18029     5d/pop-to-ebp
18030     c3/return
18031 
18032 $power-of-2?:abort:
18033     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
18034     (flush *(ebp+0xc))
18035     (stop *(ebp+0x10) 1)
18036     # never gets here
18037 
18038 num-shift-rights:  # n: int -> result/eax: int
18039     # precondition: n is a positive power of 2
18040     # . prologue
18041     55/push-ebp
18042     89/<- %ebp 4/r32/esp
18043     # . save registers
18044     51/push-ecx
18045     # var curr/ecx: int = n
18046     8b/-> *(ebp+8) 1/r32/ecx
18047     # result = 0
18048     b8/copy-to-eax 0/imm32
18049     {
18050       # if (curr <= 1) break
18051       81 7/subop/compare %ecx 1/imm32
18052       7e/jump-if-<= break/disp8
18053       40/increment-eax
18054       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
18055       eb/jump loop/disp8
18056     }
18057 $num-shift-rights:end:
18058     # . restore registers
18059     59/pop-to-ecx
18060     # . epilogue
18061     89/<- %esp 5/r32/ebp
18062     5d/pop-to-ebp
18063     c3/return
18064 
18065 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
18066     # . prologue
18067     55/push-ebp
18068     89/<- %ebp 4/r32/esp
18069     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
18070     8b/-> *(ebp+8) 0/r32/eax
18071     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18072     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
18073     # var output-var/eax: (addr var) = second-inout->value
18074     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18075 #?     (write-buffered Stderr "mu-get-offset: ")
18076 #?     (write-int32-hex-buffered Stderr %eax)
18077 #?     (write-buffered Stderr " name: ")
18078 #?     50/push-eax
18079 #?     (lookup *eax *(eax+4))  # Var-name
18080 #?     (write-buffered Stderr %eax)
18081 #?     58/pop-to-eax
18082 #?     (write-buffered Stderr Newline)
18083 #?     (flush Stderr)
18084     # return output-var->stack-offset
18085     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
18086 #?     (write-buffered Stderr "=> ")
18087 #?     (write-int32-hex-buffered Stderr %eax)
18088 #?     (write-buffered Stderr Newline)
18089 #?     (flush Stderr)
18090 $emit-get-offset:end:
18091     # . epilogue
18092     89/<- %esp 5/r32/ebp
18093     5d/pop-to-ebp
18094     c3/return
18095 
18096 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)
18097     # . prologue
18098     55/push-ebp
18099     89/<- %ebp 4/r32/esp
18100     # . save registers
18101     50/push-eax
18102     51/push-ecx
18103     56/push-esi
18104     # esi = block
18105     8b/-> *(ebp+0xc) 6/r32/esi
18106     # block->var->block-depth = *Curr-block-depth
18107     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
18108     8b/-> *Curr-block-depth 1/r32/ecx
18109     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
18110     # var stmts/eax: (addr list stmt) = lookup(block->statements)
18111     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
18112     #
18113     {
18114 $emit-subx-block:check-empty:
18115       3d/compare-eax-and 0/imm32
18116       0f 84/jump-if-= break/disp32
18117       (emit-indent *(ebp+8) *Curr-block-depth)
18118       (write-buffered *(ebp+8) "{\n")
18119       # var v/ecx: (addr var) = lookup(block->var)
18120       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
18121       89/<- %ecx 0/r32/eax
18122       #
18123       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18124       (write-buffered *(ebp+8) %eax)
18125       (write-buffered *(ebp+8) ":loop:\n")
18126       ff 0/subop/increment *Curr-block-depth
18127       (push *(ebp+0x10) *(esi+0xc))  # Block-var
18128       (push *(ebp+0x10) *(esi+0x10))  # Block-var
18129       (push *(ebp+0x10) 0)  # false
18130       # emit block->statements
18131       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
18132       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
18133       (pop *(ebp+0x10))  # => eax
18134       (pop *(ebp+0x10))  # => eax
18135       (pop *(ebp+0x10))  # => eax
18136       ff 1/subop/decrement *Curr-block-depth
18137       (emit-indent *(ebp+8) *Curr-block-depth)
18138       (write-buffered *(ebp+8) "}\n")
18139       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
18140       (write-buffered *(ebp+8) %eax)
18141       (write-buffered *(ebp+8) ":break:\n")
18142     }
18143 $emit-subx-block:end:
18144     # . restore registers
18145     5e/pop-to-esi
18146     59/pop-to-ecx
18147     58/pop-to-eax
18148     # . epilogue
18149     89/<- %esp 5/r32/ebp
18150     5d/pop-to-ebp
18151     c3/return
18152 
18153 # Primitives supported
18154 # See mu_instructions for a summary of this linked-list data structure.
18155 #
18156 # For each operation, put variants with hard-coded registers before flexible ones.
18157 #
18158 # Unfortunately, our restrictions on addresses require that various fields in
18159 # primitives be handles, which complicates these definitions.
18160 #   - we need to insert dummy fields all over the place for fake alloc-ids
18161 #   - we can't use our syntax sugar of quoted literals for string fields
18162 #
18163 # Fake alloc-ids are needed because our type definitions up top require
18164 # handles but it's clearer to statically allocate these long-lived objects.
18165 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
18166 #
18167 # Every 'object' below starts with a fake alloc-id. It may also contain other
18168 # fake alloc-ids for various handle fields.
18169 #
18170 # I think of objects starting with a fake alloc-id as having type 'payload'.
18171 # It's not really intended to be created dynamically; for that use `allocate`
18172 # as usual.
18173 #
18174 # Idea for a notation to simplify such definitions:
18175 #   _Primitive-increment-eax:  # (payload primitive)
18176 #     0x11/alloc-id:fake:payload
18177 #     0x11 @(0x11 "increment")  # name
18178 #     0 0                       # inouts
18179 #     0x11 @(0x11/payload
18180 #            0x11 @(0x11/payload  # List-value
18181 #                   0 0             # Var-name
18182 #                   0x11 @(0x11     # Var-type
18183 #                          1/is-atom
18184 #                          1/value 0/unused   # Type-tree-left
18185 #                          0 0                # Type-tree-right
18186 #                         )
18187 #                   1               # block-depth
18188 #                   0               # stack-offset
18189 #                   0x11 @(0x11 "eax")  # Var-register
18190 #                  )
18191 #            0 0)                 # List-next
18192 #     ...
18193 #     _Primitive-increment-ecx/imm32/next
18194 #   ...
18195 # Awfully complex and non-obvious. But also clearly signals there's something
18196 # to learn here, so may be worth trying.
18197 #
18198 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
18199 #
18200 # For now we'll continue to just use comments and manually ensure they stay up
18201 # to date.
18202 == data
18203 Primitives:  # (addr primitive)
18204 # - increment/decrement
18205 _Primitive-increment-eax:  # (addr primitive)
18206     # var/eax <- increment => 40/increment-eax
18207     0x11/imm32/alloc-id:fake
18208     _string-increment/imm32/name
18209     0/imm32/no-inouts
18210     0/imm32/no-inouts
18211     0x11/imm32/alloc-id:fake
18212     Single-int-var-in-eax/imm32/outputs
18213     0x11/imm32/alloc-id:fake
18214     _string_40_increment_eax/imm32/subx-name
18215     0/imm32/no-rm32
18216     0/imm32/no-r32
18217     0/imm32/no-imm32
18218     0/imm32/no-imm8
18219     0/imm32/no-disp32
18220     0/imm32/no-xm32
18221     0/imm32/no-x32
18222     0x11/imm32/alloc-id:fake
18223     _Primitive-increment-ecx/imm32/next
18224 _Primitive-increment-ecx:  # (payload primitive)
18225     0x11/imm32/alloc-id:fake:payload
18226     # var/ecx <- increment => 41/increment-ecx
18227     0x11/imm32/alloc-id:fake
18228     _string-increment/imm32/name
18229     0/imm32/no-inouts
18230     0/imm32/no-inouts
18231     0x11/imm32/alloc-id:fake
18232     Single-int-var-in-ecx/imm32/outputs
18233     0x11/imm32/alloc-id:fake
18234     _string_41_increment_ecx/imm32/subx-name
18235     0/imm32/no-rm32
18236     0/imm32/no-r32
18237     0/imm32/no-imm32
18238     0/imm32/no-imm8
18239     0/imm32/no-disp32
18240     0/imm32/no-xm32
18241     0/imm32/no-x32
18242     0x11/imm32/alloc-id:fake
18243     _Primitive-increment-edx/imm32/next
18244 _Primitive-increment-edx:  # (payload primitive)
18245     0x11/imm32/alloc-id:fake:payload
18246     # var/edx <- increment => 42/increment-edx
18247     0x11/imm32/alloc-id:fake
18248     _string-increment/imm32/name
18249     0/imm32/no-inouts
18250     0/imm32/no-inouts
18251     0x11/imm32/alloc-id:fake
18252     Single-int-var-in-edx/imm32/outputs
18253     0x11/imm32/alloc-id:fake
18254     _string_42_increment_edx/imm32/subx-name
18255     0/imm32/no-rm32
18256     0/imm32/no-r32
18257     0/imm32/no-imm32
18258     0/imm32/no-imm8
18259     0/imm32/no-disp32
18260     0/imm32/no-xm32
18261     0/imm32/no-x32
18262     0x11/imm32/alloc-id:fake
18263     _Primitive-increment-ebx/imm32/next
18264 _Primitive-increment-ebx:  # (payload primitive)
18265     0x11/imm32/alloc-id:fake:payload
18266     # var/ebx <- increment => 43/increment-ebx
18267     0x11/imm32/alloc-id:fake
18268     _string-increment/imm32/name
18269     0/imm32/no-inouts
18270     0/imm32/no-inouts
18271     0x11/imm32/alloc-id:fake
18272     Single-int-var-in-ebx/imm32/outputs
18273     0x11/imm32/alloc-id:fake
18274     _string_43_increment_ebx/imm32/subx-name
18275     0/imm32/no-rm32
18276     0/imm32/no-r32
18277     0/imm32/no-imm32
18278     0/imm32/no-imm8
18279     0/imm32/no-disp32
18280     0/imm32/no-xm32
18281     0/imm32/no-x32
18282     0x11/imm32/alloc-id:fake
18283     _Primitive-increment-esi/imm32/next
18284 _Primitive-increment-esi:  # (payload primitive)
18285     0x11/imm32/alloc-id:fake:payload
18286     # var/esi <- increment => 46/increment-esi
18287     0x11/imm32/alloc-id:fake
18288     _string-increment/imm32/name
18289     0/imm32/no-inouts
18290     0/imm32/no-inouts
18291     0x11/imm32/alloc-id:fake
18292     Single-int-var-in-esi/imm32/outputs
18293     0x11/imm32/alloc-id:fake
18294     _string_46_increment_esi/imm32/subx-name
18295     0/imm32/no-rm32
18296     0/imm32/no-r32
18297     0/imm32/no-imm32
18298     0/imm32/no-imm8
18299     0/imm32/no-disp32
18300     0/imm32/no-xm32
18301     0/imm32/no-x32
18302     0x11/imm32/alloc-id:fake
18303     _Primitive-increment-edi/imm32/next
18304 _Primitive-increment-edi:  # (payload primitive)
18305     0x11/imm32/alloc-id:fake:payload
18306     # var/edi <- increment => 47/increment-edi
18307     0x11/imm32/alloc-id:fake
18308     _string-increment/imm32/name
18309     0/imm32/no-inouts
18310     0/imm32/no-inouts
18311     0x11/imm32/alloc-id:fake
18312     Single-int-var-in-edi/imm32/outputs
18313     0x11/imm32/alloc-id:fake
18314     _string_47_increment_edi/imm32/subx-name
18315     0/imm32/no-rm32
18316     0/imm32/no-r32
18317     0/imm32/no-imm32
18318     0/imm32/no-imm8
18319     0/imm32/no-disp32
18320     0/imm32/no-xm32
18321     0/imm32/no-x32
18322     0x11/imm32/alloc-id:fake
18323     _Primitive-decrement-eax/imm32/next
18324 _Primitive-decrement-eax:  # (payload primitive)
18325     0x11/imm32/alloc-id:fake:payload
18326     # var/eax <- decrement => 48/decrement-eax
18327     0x11/imm32/alloc-id:fake
18328     _string-decrement/imm32/name
18329     0/imm32/no-inouts
18330     0/imm32/no-inouts
18331     0x11/imm32/alloc-id:fake
18332     Single-int-var-in-eax/imm32/outputs
18333     0x11/imm32/alloc-id:fake
18334     _string_48_decrement_eax/imm32/subx-name
18335     0/imm32/no-rm32
18336     0/imm32/no-r32
18337     0/imm32/no-imm32
18338     0/imm32/no-imm8
18339     0/imm32/no-disp32
18340     0/imm32/no-xm32
18341     0/imm32/no-x32
18342     0x11/imm32/alloc-id:fake
18343     _Primitive-decrement-ecx/imm32/next
18344 _Primitive-decrement-ecx:  # (payload primitive)
18345     0x11/imm32/alloc-id:fake:payload
18346     # var/ecx <- decrement => 49/decrement-ecx
18347     0x11/imm32/alloc-id:fake
18348     _string-decrement/imm32/name
18349     0/imm32/no-inouts
18350     0/imm32/no-inouts
18351     0x11/imm32/alloc-id:fake
18352     Single-int-var-in-ecx/imm32/outputs
18353     0x11/imm32/alloc-id:fake
18354     _string_49_decrement_ecx/imm32/subx-name
18355     0/imm32/no-rm32
18356     0/imm32/no-r32
18357     0/imm32/no-imm32
18358     0/imm32/no-imm8
18359     0/imm32/no-disp32
18360     0/imm32/no-xm32
18361     0/imm32/no-x32
18362     0x11/imm32/alloc-id:fake
18363     _Primitive-decrement-edx/imm32/next
18364 _Primitive-decrement-edx:  # (payload primitive)
18365     0x11/imm32/alloc-id:fake:payload
18366     # var/edx <- decrement => 4a/decrement-edx
18367     0x11/imm32/alloc-id:fake
18368     _string-decrement/imm32/name
18369     0/imm32/no-inouts
18370     0/imm32/no-inouts
18371     0x11/imm32/alloc-id:fake
18372     Single-int-var-in-edx/imm32/outputs
18373     0x11/imm32/alloc-id:fake
18374     _string_4a_decrement_edx/imm32/subx-name
18375     0/imm32/no-rm32
18376     0/imm32/no-r32
18377     0/imm32/no-imm32
18378     0/imm32/no-imm8
18379     0/imm32/no-disp32
18380     0/imm32/no-xm32
18381     0/imm32/no-x32
18382     0x11/imm32/alloc-id:fake
18383     _Primitive-decrement-ebx/imm32/next
18384 _Primitive-decrement-ebx:  # (payload primitive)
18385     0x11/imm32/alloc-id:fake:payload
18386     # var/ebx <- decrement => 4b/decrement-ebx
18387     0x11/imm32/alloc-id:fake
18388     _string-decrement/imm32/name
18389     0/imm32/no-inouts
18390     0/imm32/no-inouts
18391     0x11/imm32/alloc-id:fake
18392     Single-int-var-in-ebx/imm32/outputs
18393     0x11/imm32/alloc-id:fake
18394     _string_4b_decrement_ebx/imm32/subx-name
18395     0/imm32/no-rm32
18396     0/imm32/no-r32
18397     0/imm32/no-imm32
18398     0/imm32/no-imm8
18399     0/imm32/no-disp32
18400     0/imm32/no-xm32
18401     0/imm32/no-x32
18402     0x11/imm32/alloc-id:fake
18403     _Primitive-decrement-esi/imm32/next
18404 _Primitive-decrement-esi:  # (payload primitive)
18405     0x11/imm32/alloc-id:fake:payload
18406     # var/esi <- decrement => 4e/decrement-esi
18407     0x11/imm32/alloc-id:fake
18408     _string-decrement/imm32/name
18409     0/imm32/no-inouts
18410     0/imm32/no-inouts
18411     0x11/imm32/alloc-id:fake
18412     Single-int-var-in-esi/imm32/outputs
18413     0x11/imm32/alloc-id:fake
18414     _string_4e_decrement_esi/imm32/subx-name
18415     0/imm32/no-rm32
18416     0/imm32/no-r32
18417     0/imm32/no-imm32
18418     0/imm32/no-imm8
18419     0/imm32/no-disp32
18420     0/imm32/no-xm32
18421     0/imm32/no-x32
18422     0x11/imm32/alloc-id:fake
18423     _Primitive-decrement-edi/imm32/next
18424 _Primitive-decrement-edi:  # (payload primitive)
18425     0x11/imm32/alloc-id:fake:payload
18426     # var/edi <- decrement => 4f/decrement-edi
18427     0x11/imm32/alloc-id:fake
18428     _string-decrement/imm32/name
18429     0/imm32/no-inouts
18430     0/imm32/no-inouts
18431     0x11/imm32/alloc-id:fake
18432     Single-int-var-in-edi/imm32/outputs
18433     0x11/imm32/alloc-id:fake
18434     _string_4f_decrement_edi/imm32/subx-name
18435     0/imm32/no-rm32
18436     0/imm32/no-r32
18437     0/imm32/no-imm32
18438     0/imm32/no-imm8
18439     0/imm32/no-disp32
18440     0/imm32/no-xm32
18441     0/imm32/no-x32
18442     0x11/imm32/alloc-id:fake
18443     _Primitive-increment-mem/imm32/next
18444 _Primitive-increment-mem:  # (payload primitive)
18445     0x11/imm32/alloc-id:fake:payload
18446     # increment var => ff 0/subop/increment *(ebp+__)
18447     0x11/imm32/alloc-id:fake
18448     _string-increment/imm32/name
18449     0x11/imm32/alloc-id:fake
18450     Single-int-var-in-mem/imm32/inouts
18451     0/imm32/no-outputs
18452     0/imm32/no-outputs
18453     0x11/imm32/alloc-id:fake
18454     _string_ff_subop_increment/imm32/subx-name
18455     1/imm32/rm32-is-first-inout
18456     0/imm32/no-r32
18457     0/imm32/no-imm32
18458     0/imm32/no-imm8
18459     0/imm32/no-disp32
18460     0/imm32/no-xm32
18461     0/imm32/no-x32
18462     0x11/imm32/alloc-id:fake
18463     _Primitive-increment-reg/imm32/next
18464 _Primitive-increment-reg:  # (payload primitive)
18465     0x11/imm32/alloc-id:fake:payload
18466     # var/reg <- increment => ff 0/subop/increment %__
18467     0x11/imm32/alloc-id:fake
18468     _string-increment/imm32/name
18469     0/imm32/no-inouts
18470     0/imm32/no-inouts
18471     0x11/imm32/alloc-id:fake
18472     Single-int-var-in-some-register/imm32/outputs
18473     0x11/imm32/alloc-id:fake
18474     _string_ff_subop_increment/imm32/subx-name
18475     3/imm32/rm32-is-first-output
18476     0/imm32/no-r32
18477     0/imm32/no-imm32
18478     0/imm32/no-imm8
18479     0/imm32/no-disp32
18480     0/imm32/no-xm32
18481     0/imm32/no-x32
18482     0x11/imm32/alloc-id:fake
18483     _Primitive-decrement-mem/imm32/next
18484 _Primitive-decrement-mem:  # (payload primitive)
18485     0x11/imm32/alloc-id:fake:payload
18486     # decrement var => ff 1/subop/decrement *(ebp+__)
18487     0x11/imm32/alloc-id:fake
18488     _string-decrement/imm32/name
18489     0x11/imm32/alloc-id:fake
18490     Single-int-var-in-mem/imm32/inouts
18491     0/imm32/no-outputs
18492     0/imm32/no-outputs
18493     0x11/imm32/alloc-id:fake
18494     _string_ff_subop_decrement/imm32/subx-name
18495     1/imm32/rm32-is-first-inout
18496     0/imm32/no-r32
18497     0/imm32/no-imm32
18498     0/imm32/no-imm8
18499     0/imm32/no-disp32
18500     0/imm32/no-xm32
18501     0/imm32/no-x32
18502     0x11/imm32/alloc-id:fake
18503     _Primitive-decrement-reg/imm32/next
18504 _Primitive-decrement-reg:  # (payload primitive)
18505     0x11/imm32/alloc-id:fake:payload
18506     # var/reg <- decrement => ff 1/subop/decrement %__
18507     0x11/imm32/alloc-id:fake
18508     _string-decrement/imm32/name
18509     0/imm32/no-inouts
18510     0/imm32/no-inouts
18511     0x11/imm32/alloc-id:fake
18512     Single-int-var-in-some-register/imm32/outputs
18513     0x11/imm32/alloc-id:fake
18514     _string_ff_subop_decrement/imm32/subx-name
18515     3/imm32/rm32-is-first-output
18516     0/imm32/no-r32
18517     0/imm32/no-imm32
18518     0/imm32/no-imm8
18519     0/imm32/no-disp32
18520     0/imm32/no-xm32
18521     0/imm32/no-x32
18522     0x11/imm32/alloc-id:fake
18523     _Primitive-add-to-eax/imm32/next
18524 # - add
18525 _Primitive-add-to-eax:  # (payload primitive)
18526     0x11/imm32/alloc-id:fake:payload
18527     # var/eax <- add lit => 05/add-to-eax lit/imm32
18528     0x11/imm32/alloc-id:fake
18529     _string-add/imm32/name
18530     0x11/imm32/alloc-id:fake
18531     Single-lit-var/imm32/inouts
18532     0x11/imm32/alloc-id:fake
18533     Single-int-var-in-eax/imm32/outputs
18534     0x11/imm32/alloc-id:fake
18535     _string_05_add_to_eax/imm32/subx-name
18536     0/imm32/no-rm32
18537     0/imm32/no-r32
18538     1/imm32/imm32-is-first-inout
18539     0/imm32/no-imm8
18540     0/imm32/no-disp32
18541     0/imm32/no-xm32
18542     0/imm32/no-x32
18543     0x11/imm32/alloc-id:fake
18544     _Primitive-add-reg-to-reg/imm32/next
18545 _Primitive-add-reg-to-reg:  # (payload primitive)
18546     0x11/imm32/alloc-id:fake:payload
18547     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
18548     0x11/imm32/alloc-id:fake
18549     _string-add/imm32/name
18550     0x11/imm32/alloc-id:fake
18551     Single-int-var-in-some-register/imm32/inouts
18552     0x11/imm32/alloc-id:fake
18553     Single-int-var-in-some-register/imm32/outputs
18554     0x11/imm32/alloc-id:fake
18555     _string_01_add_to/imm32/subx-name
18556     3/imm32/rm32-is-first-output
18557     1/imm32/r32-is-first-inout
18558     0/imm32/no-imm32
18559     0/imm32/no-imm8
18560     0/imm32/no-disp32
18561     0/imm32/no-xm32
18562     0/imm32/no-x32
18563     0x11/imm32/alloc-id:fake
18564     _Primitive-add-reg-to-mem/imm32/next
18565 _Primitive-add-reg-to-mem:  # (payload primitive)
18566     0x11/imm32/alloc-id:fake:payload
18567     # add-to var1 var2/reg => 01/add-to var1 var2/r32
18568     0x11/imm32/alloc-id:fake
18569     _string-add-to/imm32/name
18570     0x11/imm32/alloc-id:fake
18571     Two-args-int-stack-int-reg/imm32/inouts
18572     0/imm32/no-outputs
18573     0/imm32/no-outputs
18574     0x11/imm32/alloc-id:fake
18575     _string_01_add_to/imm32/subx-name
18576     1/imm32/rm32-is-first-inout
18577     2/imm32/r32-is-second-inout
18578     0/imm32/no-imm32
18579     0/imm32/no-imm8
18580     0/imm32/no-disp32
18581     0/imm32/no-xm32
18582     0/imm32/no-x32
18583     0x11/imm32/alloc-id:fake
18584     _Primitive-add-mem-to-reg/imm32/next
18585 _Primitive-add-mem-to-reg:  # (payload primitive)
18586     0x11/imm32/alloc-id:fake:payload
18587     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
18588     0x11/imm32/alloc-id:fake
18589     _string-add/imm32/name
18590     0x11/imm32/alloc-id:fake
18591     Single-int-var-in-mem/imm32/inouts
18592     0x11/imm32/alloc-id:fake
18593     Single-int-var-in-some-register/imm32/outputs
18594     0x11/imm32/alloc-id:fake
18595     _string_03_add/imm32/subx-name
18596     1/imm32/rm32-is-first-inout
18597     3/imm32/r32-is-first-output
18598     0/imm32/no-imm32
18599     0/imm32/no-imm8
18600     0/imm32/no-disp32
18601     0/imm32/no-xm32
18602     0/imm32/no-x32
18603     0x11/imm32/alloc-id:fake
18604     _Primitive-add-lit-to-reg/imm32/next
18605 _Primitive-add-lit-to-reg:  # (payload primitive)
18606     0x11/imm32/alloc-id:fake:payload
18607     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
18608     0x11/imm32/alloc-id:fake
18609     _string-add/imm32/name
18610     0x11/imm32/alloc-id:fake
18611     Single-lit-var/imm32/inouts
18612     0x11/imm32/alloc-id:fake
18613     Single-int-var-in-some-register/imm32/outputs
18614     0x11/imm32/alloc-id:fake
18615     _string_81_subop_add/imm32/subx-name
18616     3/imm32/rm32-is-first-output
18617     0/imm32/no-r32
18618     1/imm32/imm32-is-first-inout
18619     0/imm32/no-imm8
18620     0/imm32/no-disp32
18621     0/imm32/no-xm32
18622     0/imm32/no-x32
18623     0x11/imm32/alloc-id:fake
18624     _Primitive-add-lit-to-mem/imm32/next
18625 _Primitive-add-lit-to-mem:  # (payload primitive)
18626     0x11/imm32/alloc-id:fake:payload
18627     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
18628     0x11/imm32/alloc-id:fake
18629     _string-add-to/imm32/name
18630     0x11/imm32/alloc-id:fake
18631     Int-var-and-literal/imm32/inouts
18632     0/imm32/no-outputs
18633     0/imm32/no-outputs
18634     0x11/imm32/alloc-id:fake
18635     _string_81_subop_add/imm32/subx-name
18636     1/imm32/rm32-is-first-inout
18637     0/imm32/no-r32
18638     2/imm32/imm32-is-second-inout
18639     0/imm32/no-imm8
18640     0/imm32/no-disp32
18641     0/imm32/no-xm32
18642     0/imm32/no-x32
18643     0x11/imm32/alloc-id:fake
18644     _Primitive-subtract-from-eax/imm32/next
18645 # - subtract
18646 _Primitive-subtract-from-eax:  # (payload primitive)
18647     0x11/imm32/alloc-id:fake:payload
18648     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
18649     0x11/imm32/alloc-id:fake
18650     _string-subtract/imm32/name
18651     0x11/imm32/alloc-id:fake
18652     Single-lit-var/imm32/inouts
18653     0x11/imm32/alloc-id:fake
18654     Single-int-var-in-eax/imm32/outputs
18655     0x11/imm32/alloc-id:fake
18656     _string_2d_subtract_from_eax/imm32/subx-name
18657     0/imm32/no-rm32
18658     0/imm32/no-r32
18659     1/imm32/imm32-is-first-inout
18660     0/imm32/no-imm8
18661     0/imm32/no-disp32
18662     0/imm32/no-xm32
18663     0/imm32/no-x32
18664     0x11/imm32/alloc-id:fake
18665     _Primitive-subtract-reg-from-reg/imm32/next
18666 _Primitive-subtract-reg-from-reg:  # (payload primitive)
18667     0x11/imm32/alloc-id:fake:payload
18668     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
18669     0x11/imm32/alloc-id:fake
18670     _string-subtract/imm32/name
18671     0x11/imm32/alloc-id:fake
18672     Single-int-var-in-some-register/imm32/inouts
18673     0x11/imm32/alloc-id:fake
18674     Single-int-var-in-some-register/imm32/outputs
18675     0x11/imm32/alloc-id:fake
18676     _string_29_subtract_from/imm32/subx-name
18677     3/imm32/rm32-is-first-output
18678     1/imm32/r32-is-first-inout
18679     0/imm32/no-imm32
18680     0/imm32/no-imm8
18681     0/imm32/no-disp32
18682     0/imm32/no-xm32
18683     0/imm32/no-x32
18684     0x11/imm32/alloc-id:fake
18685     _Primitive-subtract-reg-from-mem/imm32/next
18686 _Primitive-subtract-reg-from-mem:  # (payload primitive)
18687     0x11/imm32/alloc-id:fake:payload
18688     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
18689     0x11/imm32/alloc-id:fake
18690     _string-subtract-from/imm32/name
18691     0x11/imm32/alloc-id:fake
18692     Two-args-int-stack-int-reg/imm32/inouts
18693     0/imm32/no-outputs
18694     0/imm32/no-outputs
18695     0x11/imm32/alloc-id:fake
18696     _string_29_subtract_from/imm32/subx-name
18697     1/imm32/rm32-is-first-inout
18698     2/imm32/r32-is-second-inout
18699     0/imm32/no-imm32
18700     0/imm32/no-imm8
18701     0/imm32/no-disp32
18702     0/imm32/no-xm32
18703     0/imm32/no-x32
18704     0x11/imm32/alloc-id:fake
18705     _Primitive-subtract-mem-from-reg/imm32/next
18706 _Primitive-subtract-mem-from-reg:  # (payload primitive)
18707     0x11/imm32/alloc-id:fake:payload
18708     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
18709     0x11/imm32/alloc-id:fake
18710     _string-subtract/imm32/name
18711     0x11/imm32/alloc-id:fake
18712     Single-int-var-in-mem/imm32/inouts
18713     0x11/imm32/alloc-id:fake
18714     Single-int-var-in-some-register/imm32/outputs
18715     0x11/imm32/alloc-id:fake
18716     _string_2b_subtract/imm32/subx-name
18717     1/imm32/rm32-is-first-inout
18718     3/imm32/r32-is-first-output
18719     0/imm32/no-imm32
18720     0/imm32/no-imm8
18721     0/imm32/no-disp32
18722     0/imm32/no-xm32
18723     0/imm32/no-x32
18724     0x11/imm32/alloc-id:fake
18725     _Primitive-subtract-lit-from-reg/imm32/next
18726 _Primitive-subtract-lit-from-reg:  # (payload primitive)
18727     0x11/imm32/alloc-id:fake:payload
18728     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
18729     0x11/imm32/alloc-id:fake
18730     _string-subtract/imm32/name
18731     0x11/imm32/alloc-id:fake
18732     Single-lit-var/imm32/inouts
18733     0x11/imm32/alloc-id:fake
18734     Single-int-var-in-some-register/imm32/outputs
18735     0x11/imm32/alloc-id:fake
18736     _string_81_subop_subtract/imm32/subx-name
18737     3/imm32/rm32-is-first-output
18738     0/imm32/no-r32
18739     1/imm32/imm32-is-first-inout
18740     0/imm32/no-imm8
18741     0/imm32/no-disp32
18742     0/imm32/no-xm32
18743     0/imm32/no-x32
18744     0x11/imm32/alloc-id:fake
18745     _Primitive-subtract-lit-from-mem/imm32/next
18746 _Primitive-subtract-lit-from-mem:  # (payload primitive)
18747     0x11/imm32/alloc-id:fake:payload
18748     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
18749     0x11/imm32/alloc-id:fake
18750     _string-subtract-from/imm32/name
18751     0x11/imm32/alloc-id:fake
18752     Int-var-and-literal/imm32/inouts
18753     0/imm32/no-outputs
18754     0/imm32/no-outputs
18755     0x11/imm32/alloc-id:fake
18756     _string_81_subop_subtract/imm32/subx-name
18757     1/imm32/rm32-is-first-inout
18758     0/imm32/no-r32
18759     2/imm32/imm32-is-second-inout
18760     0/imm32/no-imm8
18761     0/imm32/no-disp32
18762     0/imm32/no-xm32
18763     0/imm32/no-x32
18764     0x11/imm32/alloc-id:fake
18765     _Primitive-and-with-eax/imm32/next
18766 # - and
18767 _Primitive-and-with-eax:  # (payload primitive)
18768     0x11/imm32/alloc-id:fake:payload
18769     # var/eax <- and lit => 25/and-with-eax lit/imm32
18770     0x11/imm32/alloc-id:fake
18771     _string-and/imm32/name
18772     0x11/imm32/alloc-id:fake
18773     Single-lit-var/imm32/inouts
18774     0x11/imm32/alloc-id:fake
18775     Single-int-var-in-eax/imm32/outputs
18776     0x11/imm32/alloc-id:fake
18777     _string_25_and_with_eax/imm32/subx-name
18778     0/imm32/no-rm32
18779     0/imm32/no-r32
18780     1/imm32/imm32-is-first-inout
18781     0/imm32/no-imm8
18782     0/imm32/no-disp32
18783     0/imm32/no-xm32
18784     0/imm32/no-x32
18785     0x11/imm32/alloc-id:fake
18786     _Primitive-and-reg-with-reg/imm32/next
18787 _Primitive-and-reg-with-reg:  # (payload primitive)
18788     0x11/imm32/alloc-id:fake:payload
18789     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
18790     0x11/imm32/alloc-id:fake
18791     _string-and/imm32/name
18792     0x11/imm32/alloc-id:fake
18793     Single-int-var-in-some-register/imm32/inouts
18794     0x11/imm32/alloc-id:fake
18795     Single-int-var-in-some-register/imm32/outputs
18796     0x11/imm32/alloc-id:fake
18797     _string_21_and_with/imm32/subx-name
18798     3/imm32/rm32-is-first-output
18799     1/imm32/r32-is-first-inout
18800     0/imm32/no-imm32
18801     0/imm32/no-imm8
18802     0/imm32/no-disp32
18803     0/imm32/no-xm32
18804     0/imm32/no-x32
18805     0x11/imm32/alloc-id:fake
18806     _Primitive-and-reg-with-mem/imm32/next
18807 _Primitive-and-reg-with-mem:  # (payload primitive)
18808     0x11/imm32/alloc-id:fake:payload
18809     # and-with var1 var2/reg => 21/and-with var1 var2/r32
18810     0x11/imm32/alloc-id:fake
18811     _string-and-with/imm32/name
18812     0x11/imm32/alloc-id:fake
18813     Two-args-int-stack-int-reg/imm32/inouts
18814     0/imm32/no-outputs
18815     0/imm32/no-outputs
18816     0x11/imm32/alloc-id:fake
18817     _string_21_and_with/imm32/subx-name
18818     1/imm32/rm32-is-first-inout
18819     2/imm32/r32-is-second-inout
18820     0/imm32/no-imm32
18821     0/imm32/no-imm8
18822     0/imm32/no-disp32
18823     0/imm32/no-xm32
18824     0/imm32/no-x32
18825     0x11/imm32/alloc-id:fake
18826     _Primitive-and-mem-with-reg/imm32/next
18827 _Primitive-and-mem-with-reg:  # (payload primitive)
18828     0x11/imm32/alloc-id:fake:payload
18829     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
18830     0x11/imm32/alloc-id:fake
18831     _string-and/imm32/name
18832     0x11/imm32/alloc-id:fake
18833     Single-int-var-in-mem/imm32/inouts
18834     0x11/imm32/alloc-id:fake
18835     Single-int-var-in-some-register/imm32/outputs
18836     0x11/imm32/alloc-id:fake
18837     _string_23_and/imm32/subx-name
18838     1/imm32/rm32-is-first-inout
18839     3/imm32/r32-is-first-output
18840     0/imm32/no-imm32
18841     0/imm32/no-imm8
18842     0/imm32/no-disp32
18843     0/imm32/no-xm32
18844     0/imm32/no-x32
18845     0x11/imm32/alloc-id:fake
18846     _Primitive-and-lit-with-reg/imm32/next
18847 _Primitive-and-lit-with-reg:  # (payload primitive)
18848     0x11/imm32/alloc-id:fake:payload
18849     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
18850     0x11/imm32/alloc-id:fake
18851     _string-and/imm32/name
18852     0x11/imm32/alloc-id:fake
18853     Single-lit-var/imm32/inouts
18854     0x11/imm32/alloc-id:fake
18855     Single-int-var-in-some-register/imm32/outputs
18856     0x11/imm32/alloc-id:fake
18857     _string_81_subop_and/imm32/subx-name
18858     3/imm32/rm32-is-first-output
18859     0/imm32/no-r32
18860     1/imm32/imm32-is-first-inout
18861     0/imm32/no-imm8
18862     0/imm32/no-disp32
18863     0/imm32/no-xm32
18864     0/imm32/no-x32
18865     0x11/imm32/alloc-id:fake
18866     _Primitive-and-lit-with-mem/imm32/next
18867 _Primitive-and-lit-with-mem:  # (payload primitive)
18868     0x11/imm32/alloc-id:fake:payload
18869     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
18870     0x11/imm32/alloc-id:fake
18871     _string-and-with/imm32/name
18872     0x11/imm32/alloc-id:fake
18873     Int-var-and-literal/imm32/inouts
18874     0/imm32/no-outputs
18875     0/imm32/no-outputs
18876     0x11/imm32/alloc-id:fake
18877     _string_81_subop_and/imm32/subx-name
18878     1/imm32/rm32-is-first-inout
18879     0/imm32/no-r32
18880     2/imm32/imm32-is-second-inout
18881     0/imm32/no-imm8
18882     0/imm32/no-disp32
18883     0/imm32/no-xm32
18884     0/imm32/no-x32
18885     0x11/imm32/alloc-id:fake
18886     _Primitive-or-with-eax/imm32/next
18887 # - or
18888 _Primitive-or-with-eax:  # (payload primitive)
18889     0x11/imm32/alloc-id:fake:payload
18890     # var/eax <- or lit => 0d/or-with-eax lit/imm32
18891     0x11/imm32/alloc-id:fake
18892     _string-or/imm32/name
18893     0x11/imm32/alloc-id:fake
18894     Single-lit-var/imm32/inouts
18895     0x11/imm32/alloc-id:fake
18896     Single-int-var-in-eax/imm32/outputs
18897     0x11/imm32/alloc-id:fake
18898     _string_0d_or_with_eax/imm32/subx-name
18899     0/imm32/no-rm32
18900     0/imm32/no-r32
18901     1/imm32/imm32-is-first-inout
18902     0/imm32/no-imm8
18903     0/imm32/no-disp32
18904     0/imm32/no-xm32
18905     0/imm32/no-x32
18906     0x11/imm32/alloc-id:fake
18907     _Primitive-or-reg-with-reg/imm32/next
18908 _Primitive-or-reg-with-reg:  # (payload primitive)
18909     0x11/imm32/alloc-id:fake:payload
18910     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
18911     0x11/imm32/alloc-id:fake
18912     _string-or/imm32/name
18913     0x11/imm32/alloc-id:fake
18914     Single-int-var-in-some-register/imm32/inouts
18915     0x11/imm32/alloc-id:fake
18916     Single-int-var-in-some-register/imm32/outputs
18917     0x11/imm32/alloc-id:fake
18918     _string_09_or_with/imm32/subx-name
18919     3/imm32/rm32-is-first-output
18920     1/imm32/r32-is-first-inout
18921     0/imm32/no-imm32
18922     0/imm32/no-imm8
18923     0/imm32/no-disp32
18924     0/imm32/no-xm32
18925     0/imm32/no-x32
18926     0x11/imm32/alloc-id:fake
18927     _Primitive-or-reg-with-mem/imm32/next
18928 _Primitive-or-reg-with-mem:  # (payload primitive)
18929     0x11/imm32/alloc-id:fake:payload
18930     # or-with var1 var2/reg => 09/or-with var1 var2/r32
18931     0x11/imm32/alloc-id:fake
18932     _string-or-with/imm32/name
18933     0x11/imm32/alloc-id:fake
18934     Two-args-int-stack-int-reg/imm32/inouts
18935     0/imm32/no-outputs
18936     0/imm32/no-outputs
18937     0x11/imm32/alloc-id:fake
18938     _string_09_or_with/imm32/subx-name
18939     1/imm32/rm32-is-first-inout
18940     2/imm32/r32-is-second-inout
18941     0/imm32/no-imm32
18942     0/imm32/no-imm8
18943     0/imm32/no-disp32
18944     0/imm32/no-xm32
18945     0/imm32/no-x32
18946     0x11/imm32/alloc-id:fake
18947     _Primitive-or-mem-with-reg/imm32/next
18948 _Primitive-or-mem-with-reg:  # (payload primitive)
18949     0x11/imm32/alloc-id:fake:payload
18950     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
18951     0x11/imm32/alloc-id:fake
18952     _string-or/imm32/name
18953     0x11/imm32/alloc-id:fake
18954     Single-int-var-in-mem/imm32/inouts
18955     0x11/imm32/alloc-id:fake
18956     Single-int-var-in-some-register/imm32/outputs
18957     0x11/imm32/alloc-id:fake
18958     _string_0b_or/imm32/subx-name
18959     1/imm32/rm32-is-first-inout
18960     3/imm32/r32-is-first-output
18961     0/imm32/no-imm32
18962     0/imm32/no-imm8
18963     0/imm32/no-disp32
18964     0/imm32/no-xm32
18965     0/imm32/no-x32
18966     0x11/imm32/alloc-id:fake
18967     _Primitive-or-lit-with-reg/imm32/next
18968 _Primitive-or-lit-with-reg:  # (payload primitive)
18969     0x11/imm32/alloc-id:fake:payload
18970     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
18971     0x11/imm32/alloc-id:fake
18972     _string-or/imm32/name
18973     0x11/imm32/alloc-id:fake
18974     Single-lit-var/imm32/inouts
18975     0x11/imm32/alloc-id:fake
18976     Single-int-var-in-some-register/imm32/outputs
18977     0x11/imm32/alloc-id:fake
18978     _string_81_subop_or/imm32/subx-name
18979     3/imm32/rm32-is-first-output
18980     0/imm32/no-r32
18981     1/imm32/imm32-is-first-inout
18982     0/imm32/no-imm8
18983     0/imm32/no-disp32
18984     0/imm32/no-xm32
18985     0/imm32/no-x32
18986     0x11/imm32/alloc-id:fake
18987     _Primitive-or-lit-with-mem/imm32/next
18988 _Primitive-or-lit-with-mem:  # (payload primitive)
18989     0x11/imm32/alloc-id:fake:payload
18990     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
18991     0x11/imm32/alloc-id:fake
18992     _string-or-with/imm32/name
18993     0x11/imm32/alloc-id:fake
18994     Int-var-and-literal/imm32/inouts
18995     0/imm32/no-outputs
18996     0/imm32/no-outputs
18997     0x11/imm32/alloc-id:fake
18998     _string_81_subop_or/imm32/subx-name
18999     1/imm32/rm32-is-first-inout
19000     0/imm32/no-r32
19001     2/imm32/imm32-is-second-inout
19002     0/imm32/no-imm8
19003     0/imm32/no-disp32
19004     0/imm32/no-xm32
19005     0/imm32/no-x32
19006     0x11/imm32/alloc-id:fake
19007     _Primitive-xor-with-eax/imm32/next
19008 # - xor
19009 _Primitive-xor-with-eax:  # (payload primitive)
19010     0x11/imm32/alloc-id:fake:payload
19011     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
19012     0x11/imm32/alloc-id:fake
19013     _string-xor/imm32/name
19014     0x11/imm32/alloc-id:fake
19015     Single-lit-var/imm32/inouts
19016     0x11/imm32/alloc-id:fake
19017     Single-int-var-in-eax/imm32/outputs
19018     0x11/imm32/alloc-id:fake
19019     _string_35_xor_with_eax/imm32/subx-name
19020     0/imm32/no-rm32
19021     0/imm32/no-r32
19022     1/imm32/imm32-is-first-inout
19023     0/imm32/no-imm8
19024     0/imm32/no-disp32
19025     0/imm32/no-xm32
19026     0/imm32/no-x32
19027     0x11/imm32/alloc-id:fake
19028     _Primitive-xor-reg-with-reg/imm32/next
19029 _Primitive-xor-reg-with-reg:  # (payload primitive)
19030     0x11/imm32/alloc-id:fake:payload
19031     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
19032     0x11/imm32/alloc-id:fake
19033     _string-xor/imm32/name
19034     0x11/imm32/alloc-id:fake
19035     Single-int-var-in-some-register/imm32/inouts
19036     0x11/imm32/alloc-id:fake
19037     Single-int-var-in-some-register/imm32/outputs
19038     0x11/imm32/alloc-id:fake
19039     _string_31_xor_with/imm32/subx-name
19040     3/imm32/rm32-is-first-output
19041     1/imm32/r32-is-first-inout
19042     0/imm32/no-imm32
19043     0/imm32/no-imm8
19044     0/imm32/no-disp32
19045     0/imm32/no-xm32
19046     0/imm32/no-x32
19047     0x11/imm32/alloc-id:fake
19048     _Primitive-xor-reg-with-mem/imm32/next
19049 _Primitive-xor-reg-with-mem:  # (payload primitive)
19050     0x11/imm32/alloc-id:fake:payload
19051     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
19052     0x11/imm32/alloc-id:fake
19053     _string-xor-with/imm32/name
19054     0x11/imm32/alloc-id:fake
19055     Two-args-int-stack-int-reg/imm32/inouts
19056     0/imm32/no-outputs
19057     0/imm32/no-outputs
19058     0x11/imm32/alloc-id:fake
19059     _string_31_xor_with/imm32/subx-name
19060     1/imm32/rm32-is-first-inout
19061     2/imm32/r32-is-second-inout
19062     0/imm32/no-imm32
19063     0/imm32/no-imm8
19064     0/imm32/no-disp32
19065     0/imm32/no-xm32
19066     0/imm32/no-x32
19067     0x11/imm32/alloc-id:fake
19068     _Primitive-xor-mem-with-reg/imm32/next
19069 _Primitive-xor-mem-with-reg:  # (payload primitive)
19070     0x11/imm32/alloc-id:fake:payload
19071     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
19072     0x11/imm32/alloc-id:fake
19073     _string-xor/imm32/name
19074     0x11/imm32/alloc-id:fake
19075     Single-int-var-in-mem/imm32/inouts
19076     0x11/imm32/alloc-id:fake
19077     Single-int-var-in-some-register/imm32/outputs
19078     0x11/imm32/alloc-id:fake
19079     _string_33_xor/imm32/subx-name
19080     1/imm32/rm32-is-first-inout
19081     3/imm32/r32-is-first-output
19082     0/imm32/no-imm32
19083     0/imm32/no-imm8
19084     0/imm32/no-disp32
19085     0/imm32/no-xm32
19086     0/imm32/no-x32
19087     0x11/imm32/alloc-id:fake
19088     _Primitive-xor-lit-with-reg/imm32/next
19089 _Primitive-xor-lit-with-reg:  # (payload primitive)
19090     0x11/imm32/alloc-id:fake:payload
19091     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
19092     0x11/imm32/alloc-id:fake
19093     _string-xor/imm32/name
19094     0x11/imm32/alloc-id:fake
19095     Single-lit-var/imm32/inouts
19096     0x11/imm32/alloc-id:fake
19097     Single-int-var-in-some-register/imm32/outputs
19098     0x11/imm32/alloc-id:fake
19099     _string_81_subop_xor/imm32/subx-name
19100     3/imm32/rm32-is-first-output
19101     0/imm32/no-r32
19102     1/imm32/imm32-is-first-inout
19103     0/imm32/no-imm8
19104     0/imm32/no-disp32
19105     0/imm32/no-xm32
19106     0/imm32/no-x32
19107     0x11/imm32/alloc-id:fake
19108     _Primitive-xor-lit-with-mem/imm32/next
19109 _Primitive-xor-lit-with-mem:  # (payload primitive)
19110     0x11/imm32/alloc-id:fake:payload
19111     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
19112     0x11/imm32/alloc-id:fake
19113     _string-xor-with/imm32/name
19114     0x11/imm32/alloc-id:fake
19115     Int-var-and-literal/imm32/inouts
19116     0/imm32/no-outputs
19117     0/imm32/no-outputs
19118     0x11/imm32/alloc-id:fake
19119     _string_81_subop_xor/imm32/subx-name
19120     1/imm32/rm32-is-first-inout
19121     0/imm32/no-r32
19122     2/imm32/imm32-is-second-inout
19123     0/imm32/no-imm8
19124     0/imm32/no-disp32
19125     0/imm32/no-xm32
19126     0/imm32/no-x32
19127     0x11/imm32/alloc-id:fake
19128     _Primitive-shift-reg-left-by-lit/imm32/next
19129 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
19130     0x11/imm32/alloc-id:fake:payload
19131     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
19132     0x11/imm32/alloc-id:fake
19133     _string-shift-left/imm32/name
19134     0x11/imm32/alloc-id:fake
19135     Single-lit-var/imm32/inouts
19136     0x11/imm32/alloc-id:fake
19137     Single-int-var-in-some-register/imm32/outputs
19138     0x11/imm32/alloc-id:fake
19139     _string_c1_subop_shift_left/imm32/subx-name
19140     3/imm32/rm32-is-first-output
19141     0/imm32/no-r32
19142     0/imm32/no-imm32
19143     1/imm32/imm8-is-first-inout
19144     0/imm32/no-disp32
19145     0/imm32/no-xm32
19146     0/imm32/no-x32
19147     0x11/imm32/alloc-id:fake
19148     _Primitive-shift-reg-right-by-lit/imm32/next
19149 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
19150     0x11/imm32/alloc-id:fake:payload
19151     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
19152     0x11/imm32/alloc-id:fake
19153     _string-shift-right/imm32/name
19154     0x11/imm32/alloc-id:fake
19155     Single-lit-var/imm32/inouts
19156     0x11/imm32/alloc-id:fake
19157     Single-int-var-in-some-register/imm32/outputs
19158     0x11/imm32/alloc-id:fake
19159     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
19160     3/imm32/rm32-is-first-output
19161     0/imm32/no-r32
19162     0/imm32/no-imm32
19163     1/imm32/imm8-is-first-inout
19164     0/imm32/no-disp32
19165     0/imm32/no-xm32
19166     0/imm32/no-x32
19167     0x11/imm32/alloc-id:fake
19168     _Primitive-shift-reg-right-signed-by-lit/imm32/next
19169 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
19170     0x11/imm32/alloc-id:fake:payload
19171     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
19172     0x11/imm32/alloc-id:fake
19173     _string-shift-right-signed/imm32/name
19174     0x11/imm32/alloc-id:fake
19175     Single-lit-var/imm32/inouts
19176     0x11/imm32/alloc-id:fake
19177     Single-int-var-in-some-register/imm32/outputs
19178     0x11/imm32/alloc-id:fake
19179     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
19180     3/imm32/rm32-is-first-output
19181     0/imm32/no-r32
19182     0/imm32/no-imm32
19183     1/imm32/imm8-is-first-inout
19184     0/imm32/no-disp32
19185     0/imm32/no-xm32
19186     0/imm32/no-x32
19187     0x11/imm32/alloc-id:fake
19188     _Primitive-shift-mem-left-by-lit/imm32/next
19189 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
19190     0x11/imm32/alloc-id:fake:payload
19191     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
19192     0x11/imm32/alloc-id:fake
19193     _string-shift-left/imm32/name
19194     0x11/imm32/alloc-id:fake
19195     Int-var-and-literal/imm32/inouts
19196     0/imm32/no-outputs
19197     0/imm32/no-outputs
19198     0x11/imm32/alloc-id:fake
19199     _string_c1_subop_shift_left/imm32/subx-name
19200     1/imm32/rm32-is-first-inout
19201     0/imm32/no-r32
19202     0/imm32/no-imm32
19203     2/imm32/imm8-is-second-inout
19204     0/imm32/no-disp32
19205     0/imm32/no-xm32
19206     0/imm32/no-x32
19207     0x11/imm32/alloc-id:fake
19208     _Primitive-shift-mem-right-by-lit/imm32/next
19209 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
19210     0x11/imm32/alloc-id:fake:payload
19211     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
19212     0x11/imm32/alloc-id:fake
19213     _string-shift-right/imm32/name
19214     0x11/imm32/alloc-id:fake
19215     Int-var-and-literal/imm32/inouts
19216     0/imm32/no-outputs
19217     0/imm32/no-outputs
19218     0x11/imm32/alloc-id:fake
19219     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
19220     1/imm32/rm32-is-first-inout
19221     0/imm32/no-r32
19222     0/imm32/no-imm32
19223     2/imm32/imm8-is-second-inout
19224     0/imm32/no-disp32
19225     0/imm32/no-xm32
19226     0/imm32/no-x32
19227     0x11/imm32/alloc-id:fake
19228     _Primitive-shift-mem-right-signed-by-lit/imm32/next
19229 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
19230     0x11/imm32/alloc-id:fake:payload
19231     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
19232     0x11/imm32/alloc-id:fake
19233     _string-shift-right-signed/imm32/name
19234     0x11/imm32/alloc-id:fake
19235     Int-var-and-literal/imm32/inouts
19236     0/imm32/no-outputs
19237     0/imm32/no-outputs
19238     0x11/imm32/alloc-id:fake
19239     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
19240     1/imm32/rm32-is-first-inout
19241     0/imm32/no-r32
19242     0/imm32/no-imm32
19243     2/imm32/imm8-is-second-inout
19244     0/imm32/no-disp32
19245     0/imm32/no-xm32
19246     0/imm32/no-x32
19247     0x11/imm32/alloc-id:fake
19248     _Primitive-copy-to-eax/imm32/next
19249 # - copy
19250 _Primitive-copy-to-eax:  # (payload primitive)
19251     0x11/imm32/alloc-id:fake:payload
19252     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
19253     0x11/imm32/alloc-id:fake
19254     _string-copy/imm32/name
19255     0x11/imm32/alloc-id:fake
19256     Single-lit-var/imm32/inouts
19257     0x11/imm32/alloc-id:fake
19258     Single-int-var-in-eax/imm32/outputs
19259     0x11/imm32/alloc-id:fake
19260     _string_b8_copy_to_eax/imm32/subx-name
19261     0/imm32/no-rm32
19262     0/imm32/no-r32
19263     1/imm32/imm32-is-first-inout
19264     0/imm32/no-imm8
19265     0/imm32/no-disp32
19266     0/imm32/no-xm32
19267     0/imm32/no-x32
19268     0x11/imm32/alloc-id:fake
19269     _Primitive-copy-to-ecx/imm32/next
19270 _Primitive-copy-to-ecx:  # (payload primitive)
19271     0x11/imm32/alloc-id:fake:payload
19272     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
19273     0x11/imm32/alloc-id:fake
19274     _string-copy/imm32/name
19275     0x11/imm32/alloc-id:fake
19276     Single-lit-var/imm32/inouts
19277     0x11/imm32/alloc-id:fake
19278     Single-int-var-in-ecx/imm32/outputs
19279     0x11/imm32/alloc-id:fake
19280     _string_b9_copy_to_ecx/imm32/subx-name
19281     0/imm32/no-rm32
19282     0/imm32/no-r32
19283     1/imm32/imm32-is-first-inout
19284     0/imm32/no-imm8
19285     0/imm32/no-disp32
19286     0/imm32/no-xm32
19287     0/imm32/no-x32
19288     0x11/imm32/alloc-id:fake
19289     _Primitive-copy-to-edx/imm32/next
19290 _Primitive-copy-to-edx:  # (payload primitive)
19291     0x11/imm32/alloc-id:fake:payload
19292     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
19293     0x11/imm32/alloc-id:fake
19294     _string-copy/imm32/name
19295     0x11/imm32/alloc-id:fake
19296     Single-lit-var/imm32/inouts
19297     0x11/imm32/alloc-id:fake
19298     Single-int-var-in-edx/imm32/outputs
19299     0x11/imm32/alloc-id:fake
19300     _string_ba_copy_to_edx/imm32/subx-name
19301     0/imm32/no-rm32
19302     0/imm32/no-r32
19303     1/imm32/imm32-is-first-inout
19304     0/imm32/no-imm8
19305     0/imm32/no-disp32
19306     0/imm32/no-xm32
19307     0/imm32/no-x32
19308     0x11/imm32/alloc-id:fake
19309     _Primitive-copy-to-ebx/imm32/next
19310 _Primitive-copy-to-ebx:  # (payload primitive)
19311     0x11/imm32/alloc-id:fake:payload
19312     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
19313     0x11/imm32/alloc-id:fake
19314     _string-copy/imm32/name
19315     0x11/imm32/alloc-id:fake
19316     Single-lit-var/imm32/inouts
19317     0x11/imm32/alloc-id:fake
19318     Single-int-var-in-ebx/imm32/outputs
19319     0x11/imm32/alloc-id:fake
19320     _string_bb_copy_to_ebx/imm32/subx-name
19321     0/imm32/no-rm32
19322     0/imm32/no-r32
19323     1/imm32/imm32-is-first-inout
19324     0/imm32/no-imm8
19325     0/imm32/no-disp32
19326     0/imm32/no-xm32
19327     0/imm32/no-x32
19328     0x11/imm32/alloc-id:fake
19329     _Primitive-copy-to-esi/imm32/next
19330 _Primitive-copy-to-esi:  # (payload primitive)
19331     0x11/imm32/alloc-id:fake:payload
19332     # var/esi <- copy lit => be/copy-to-esi lit/imm32
19333     0x11/imm32/alloc-id:fake
19334     _string-copy/imm32/name
19335     0x11/imm32/alloc-id:fake
19336     Single-lit-var/imm32/inouts
19337     0x11/imm32/alloc-id:fake
19338     Single-int-var-in-esi/imm32/outputs
19339     0x11/imm32/alloc-id:fake
19340     _string_be_copy_to_esi/imm32/subx-name
19341     0/imm32/no-rm32
19342     0/imm32/no-r32
19343     1/imm32/imm32-is-first-inout
19344     0/imm32/no-imm8
19345     0/imm32/no-disp32
19346     0/imm32/no-xm32
19347     0/imm32/no-x32
19348     0x11/imm32/alloc-id:fake
19349     _Primitive-copy-to-edi/imm32/next
19350 _Primitive-copy-to-edi:  # (payload primitive)
19351     0x11/imm32/alloc-id:fake:payload
19352     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
19353     0x11/imm32/alloc-id:fake
19354     _string-copy/imm32/name
19355     0x11/imm32/alloc-id:fake
19356     Single-lit-var/imm32/inouts
19357     0x11/imm32/alloc-id:fake
19358     Single-int-var-in-edi/imm32/outputs
19359     0x11/imm32/alloc-id:fake
19360     _string_bf_copy_to_edi/imm32/subx-name
19361     0/imm32/no-rm32
19362     0/imm32/no-r32
19363     1/imm32/imm32-is-first-inout
19364     0/imm32/no-imm8
19365     0/imm32/no-disp32
19366     0/imm32/no-xm32
19367     0/imm32/no-x32
19368     0x11/imm32/alloc-id:fake
19369     _Primitive-copy-reg-to-reg/imm32/next
19370 _Primitive-copy-reg-to-reg:  # (payload primitive)
19371     0x11/imm32/alloc-id:fake:payload
19372     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
19373     0x11/imm32/alloc-id:fake
19374     _string-copy/imm32/name
19375     0x11/imm32/alloc-id:fake
19376     Single-int-var-in-some-register/imm32/inouts
19377     0x11/imm32/alloc-id:fake
19378     Single-int-var-in-some-register/imm32/outputs
19379     0x11/imm32/alloc-id:fake
19380     _string_89_<-/imm32/subx-name
19381     3/imm32/rm32-is-first-output
19382     1/imm32/r32-is-first-inout
19383     0/imm32/no-imm32
19384     0/imm32/no-imm8
19385     0/imm32/no-disp32
19386     0/imm32/no-xm32
19387     0/imm32/no-x32
19388     0x11/imm32/alloc-id:fake
19389     _Primitive-copy-reg-to-mem/imm32/next
19390 _Primitive-copy-reg-to-mem:  # (payload primitive)
19391     0x11/imm32/alloc-id:fake:payload
19392     # copy-to var1 var2/reg => 89/<- var1 var2/r32
19393     0x11/imm32/alloc-id:fake
19394     _string-copy-to/imm32/name
19395     0x11/imm32/alloc-id:fake
19396     Two-args-int-stack-int-reg/imm32/inouts
19397     0/imm32/no-outputs
19398     0/imm32/no-outputs
19399     0x11/imm32/alloc-id:fake
19400     _string_89_<-/imm32/subx-name
19401     1/imm32/rm32-is-first-inout
19402     2/imm32/r32-is-second-inout
19403     0/imm32/no-imm32
19404     0/imm32/no-imm8
19405     0/imm32/no-disp32
19406     0/imm32/no-xm32
19407     0/imm32/no-x32
19408     0x11/imm32/alloc-id:fake
19409     _Primitive-copy-mem-to-reg/imm32/next
19410 _Primitive-copy-mem-to-reg:  # (payload primitive)
19411     0x11/imm32/alloc-id:fake:payload
19412     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
19413     0x11/imm32/alloc-id:fake
19414     _string-copy/imm32/name
19415     0x11/imm32/alloc-id:fake
19416     Single-int-var-in-mem/imm32/inouts
19417     0x11/imm32/alloc-id:fake
19418     Single-int-var-in-some-register/imm32/outputs
19419     0x11/imm32/alloc-id:fake
19420     _string_8b_->/imm32/subx-name
19421     1/imm32/rm32-is-first-inout
19422     3/imm32/r32-is-first-output
19423     0/imm32/no-imm32
19424     0/imm32/no-imm8
19425     0/imm32/no-disp32
19426     0/imm32/no-xm32
19427     0/imm32/no-x32
19428     0x11/imm32/alloc-id:fake
19429     _Primitive-copy-lit-to-reg/imm32/next
19430 _Primitive-copy-lit-to-reg:  # (payload primitive)
19431     0x11/imm32/alloc-id:fake:payload
19432     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
19433     0x11/imm32/alloc-id:fake
19434     _string-copy/imm32/name
19435     0x11/imm32/alloc-id:fake
19436     Single-lit-var/imm32/inouts
19437     0x11/imm32/alloc-id:fake
19438     Single-int-var-in-some-register/imm32/outputs
19439     0x11/imm32/alloc-id:fake
19440     _string_c7_subop_copy/imm32/subx-name
19441     3/imm32/rm32-is-first-output
19442     0/imm32/no-r32
19443     1/imm32/imm32-is-first-inout
19444     0/imm32/no-imm8
19445     0/imm32/no-disp32
19446     0/imm32/no-xm32
19447     0/imm32/no-x32
19448     0x11/imm32/alloc-id:fake
19449     _Primitive-copy-lit-to-mem/imm32/next
19450 _Primitive-copy-lit-to-mem:  # (payload primitive)
19451     0x11/imm32/alloc-id:fake:payload
19452     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
19453     0x11/imm32/alloc-id:fake
19454     _string-copy-to/imm32/name
19455     0x11/imm32/alloc-id:fake
19456     Int-var-and-literal/imm32/inouts
19457     0/imm32/no-outputs
19458     0/imm32/no-outputs
19459     0x11/imm32/alloc-id:fake
19460     _string_c7_subop_copy/imm32/subx-name
19461     1/imm32/rm32-is-first-inout
19462     0/imm32/no-r32
19463     2/imm32/imm32-is-second-inout
19464     0/imm32/no-imm8
19465     0/imm32/no-disp32
19466     0/imm32/no-xm32
19467     0/imm32/no-x32
19468     0x11/imm32/alloc-id:fake
19469     _Primitive-copy-byte-from-reg/imm32/next
19470 # - copy byte
19471 _Primitive-copy-byte-from-reg:
19472     0x11/imm32/alloc-id:fake:payload
19473     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
19474     0x11/imm32/alloc-id:fake
19475     _string-copy-byte/imm32/name
19476     0x11/imm32/alloc-id:fake
19477     Single-byte-var-in-some-register/imm32/inouts
19478     0x11/imm32/alloc-id:fake
19479     Single-byte-var-in-some-register/imm32/outputs
19480     0x11/imm32/alloc-id:fake
19481     _string_8a_copy_byte/imm32/subx-name
19482     1/imm32/rm32-is-first-inout
19483     3/imm32/r32-is-first-output
19484     0/imm32/no-imm32
19485     0/imm32/no-imm8
19486     0/imm32/no-disp32
19487     0/imm32/no-xm32
19488     0/imm32/no-x32
19489     0x11/imm32/alloc-id:fake
19490     _Primitive-copy-byte-from-mem/imm32/next
19491 _Primitive-copy-byte-from-mem:
19492     0x11/imm32/alloc-id:fake:payload
19493     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
19494     0x11/imm32/alloc-id:fake
19495     _string-copy-byte/imm32/name
19496     0x11/imm32/alloc-id:fake
19497     Single-byte-var-in-mem/imm32/inouts
19498     0x11/imm32/alloc-id:fake
19499     Single-byte-var-in-some-register/imm32/outputs
19500     0x11/imm32/alloc-id:fake
19501     _string_8a_copy_byte/imm32/subx-name
19502     1/imm32/rm32-is-first-inout
19503     3/imm32/r32-is-first-output
19504     0/imm32/no-imm32
19505     0/imm32/no-imm8
19506     0/imm32/no-disp32
19507     0/imm32/no-xm32
19508     0/imm32/no-x32
19509     0x11/imm32/alloc-id:fake
19510     _Primitive-copy-byte-to-mem/imm32/next
19511 _Primitive-copy-byte-to-mem:
19512     0x11/imm32/alloc-id:fake:payload
19513     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
19514     0x11/imm32/alloc-id:fake
19515     _string-copy-byte-to/imm32/name
19516     0x11/imm32/alloc-id:fake
19517     Two-args-byte-stack-byte-reg/imm32/inouts
19518     0/imm32/no-outputs
19519     0/imm32/no-outputs
19520     0x11/imm32/alloc-id:fake
19521     _string_88_copy_byte/imm32/subx-name
19522     1/imm32/rm32-is-first-inout
19523     2/imm32/r32-is-second-inout
19524     0/imm32/no-imm32
19525     0/imm32/no-imm8
19526     0/imm32/no-disp32
19527     0/imm32/no-xm32
19528     0/imm32/no-x32
19529     0x11/imm32/alloc-id:fake
19530     _Primitive-address/imm32/next
19531 # - address
19532 _Primitive-address:  # (payload primitive)
19533     0x11/imm32/alloc-id:fake:payload
19534     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
19535     0x11/imm32/alloc-id:fake
19536     _string-address/imm32/name
19537     0x11/imm32/alloc-id:fake
19538     Single-int-var-in-mem/imm32/inouts
19539     0x11/imm32/alloc-id:fake
19540     Single-addr-var-in-some-register/imm32/outputs
19541     0x11/imm32/alloc-id:fake
19542     _string_8d_copy_address/imm32/subx-name
19543     1/imm32/rm32-is-first-inout
19544     3/imm32/r32-is-first-output
19545     0/imm32/no-imm32
19546     0/imm32/no-imm8
19547     0/imm32/no-disp32
19548     0/imm32/no-xm32
19549     0/imm32/no-x32
19550     0x11/imm32/alloc-id:fake
19551     _Primitive-compare-reg-with-reg/imm32/next
19552 # - compare
19553 _Primitive-compare-reg-with-reg:  # (payload primitive)
19554     0x11/imm32/alloc-id:fake:payload
19555     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
19556     0x11/imm32/alloc-id:fake
19557     _string-compare/imm32/name
19558     0x11/imm32/alloc-id:fake
19559     Two-int-args-in-regs/imm32/inouts
19560     0/imm32/no-outputs
19561     0/imm32/no-outputs
19562     0x11/imm32/alloc-id:fake
19563     _string_39_compare->/imm32/subx-name
19564     1/imm32/rm32-is-first-inout
19565     2/imm32/r32-is-second-inout
19566     0/imm32/no-imm32
19567     0/imm32/no-imm8
19568     0/imm32/no-disp32
19569     0/imm32/no-xm32
19570     0/imm32/no-x32
19571     0x11/imm32/alloc-id:fake
19572     _Primitive-compare-mem-with-reg/imm32/next
19573 _Primitive-compare-mem-with-reg:  # (payload primitive)
19574     0x11/imm32/alloc-id:fake:payload
19575     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
19576     0x11/imm32/alloc-id:fake
19577     _string-compare/imm32/name
19578     0x11/imm32/alloc-id:fake
19579     Two-args-int-stack-int-reg/imm32/inouts
19580     0/imm32/no-outputs
19581     0/imm32/no-outputs
19582     0x11/imm32/alloc-id:fake
19583     _string_39_compare->/imm32/subx-name
19584     1/imm32/rm32-is-first-inout
19585     2/imm32/r32-is-second-inout
19586     0/imm32/no-imm32
19587     0/imm32/no-imm8
19588     0/imm32/no-disp32
19589     0/imm32/no-xm32
19590     0/imm32/no-x32
19591     0x11/imm32/alloc-id:fake
19592     _Primitive-compare-reg-with-mem/imm32/next
19593 _Primitive-compare-reg-with-mem:  # (payload primitive)
19594     0x11/imm32/alloc-id:fake:payload
19595     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
19596     0x11/imm32/alloc-id:fake
19597     _string-compare/imm32/name
19598     0x11/imm32/alloc-id:fake
19599     Two-args-int-reg-int-stack/imm32/inouts
19600     0/imm32/no-outputs
19601     0/imm32/no-outputs
19602     0x11/imm32/alloc-id:fake
19603     _string_3b_compare<-/imm32/subx-name
19604     2/imm32/rm32-is-second-inout
19605     1/imm32/r32-is-first-inout
19606     0/imm32/no-imm32
19607     0/imm32/no-imm8
19608     0/imm32/no-disp32
19609     0/imm32/no-xm32
19610     0/imm32/no-x32
19611     0x11/imm32/alloc-id:fake
19612     _Primitive-compare-eax-with-literal/imm32/next
19613 _Primitive-compare-eax-with-literal:  # (payload primitive)
19614     0x11/imm32/alloc-id:fake:payload
19615     # compare var1/eax n => 3d/compare-eax-with n/imm32
19616     0x11/imm32/alloc-id:fake
19617     _string-compare/imm32/name
19618     0x11/imm32/alloc-id:fake
19619     Two-args-int-eax-int-literal/imm32/inouts
19620     0/imm32/no-outputs
19621     0/imm32/no-outputs
19622     0x11/imm32/alloc-id:fake
19623     _string_3d_compare_eax_with/imm32/subx-name
19624     0/imm32/no-rm32
19625     0/imm32/no-r32
19626     2/imm32/imm32-is-second-inout
19627     0/imm32/no-imm8
19628     0/imm32/no-disp32
19629     0/imm32/no-xm32
19630     0/imm32/no-x32
19631     0x11/imm32/alloc-id:fake
19632     _Primitive-compare-reg-with-literal/imm32/next
19633 _Primitive-compare-reg-with-literal:  # (payload primitive)
19634     0x11/imm32/alloc-id:fake:payload
19635     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
19636     0x11/imm32/alloc-id:fake
19637     _string-compare/imm32/name
19638     0x11/imm32/alloc-id:fake
19639     Int-var-in-register-and-literal/imm32/inouts
19640     0/imm32/no-outputs
19641     0/imm32/no-outputs
19642     0x11/imm32/alloc-id:fake
19643     _string_81_subop_compare/imm32/subx-name
19644     1/imm32/rm32-is-first-inout
19645     0/imm32/no-r32
19646     2/imm32/imm32-is-second-inout
19647     0/imm32/no-imm8
19648     0/imm32/no-disp32
19649     0/imm32/no-xm32
19650     0/imm32/no-x32
19651     0x11/imm32/alloc-id:fake
19652     _Primitive-compare-mem-with-literal/imm32/next
19653 _Primitive-compare-mem-with-literal:  # (payload primitive)
19654     0x11/imm32/alloc-id:fake:payload
19655     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
19656     0x11/imm32/alloc-id:fake
19657     _string-compare/imm32/name
19658     0x11/imm32/alloc-id:fake
19659     Int-var-and-literal/imm32/inouts
19660     0/imm32/no-outputs
19661     0/imm32/no-outputs
19662     0x11/imm32/alloc-id:fake
19663     _string_81_subop_compare/imm32/subx-name
19664     1/imm32/rm32-is-first-inout
19665     0/imm32/no-r32
19666     2/imm32/imm32-is-second-inout
19667     0/imm32/no-imm8
19668     0/imm32/no-disp32
19669     0/imm32/no-xm32
19670     0/imm32/no-x32
19671     0x11/imm32/alloc-id:fake
19672     _Primitive-negate-reg/imm32/next
19673 # - negate
19674 _Primitive-negate-reg:  # (payload primitive)
19675     0x11/imm32/alloc-id:fake:payload
19676     # var1/reg <- negate => f7 3/subop/negate var1/rm32
19677     0x11/imm32/alloc-id:fake
19678     _string-negate/imm32/name
19679     0/imm32/no-inouts
19680     0/imm32/no-inouts
19681     0x11/imm32/alloc-id:fake
19682     Single-int-var-in-some-register/imm32/outputs
19683     0x11/imm32/alloc-id:fake
19684     _string_f7_subop_negate/imm32/subx-name
19685     3/imm32/rm32-is-first-output
19686     0/imm32/no-r32
19687     0/imm32/no-imm32
19688     0/imm32/no-imm8
19689     0/imm32/no-disp32
19690     0/imm32/no-xm32
19691     0/imm32/no-x32
19692     0x11/imm32/alloc-id:fake
19693     _Primitive-negate-mem/imm32/next
19694 _Primitive-negate-mem:  # (payload primitive)
19695     0x11/imm32/alloc-id:fake:payload
19696     # negate var1 => f7 3/subop/negate var1/rm32
19697     0x11/imm32/alloc-id:fake
19698     _string-negate/imm32/name
19699     0x11/imm32/alloc-id:fake
19700     Single-int-var-in-mem/imm32/inouts
19701     0/imm32/no-outputs
19702     0/imm32/no-outputs
19703     0x11/imm32/alloc-id:fake
19704     _string_f7_subop_negate/imm32/subx-name
19705     1/imm32/rm32-is-first-inout
19706     0/imm32/no-r32
19707     0/imm32/no-imm32
19708     0/imm32/no-imm8
19709     0/imm32/no-disp32
19710     0/imm32/no-xm32
19711     0/imm32/no-x32
19712     0x11/imm32/alloc-id:fake
19713     _Primitive-multiply-reg-by-reg/imm32/next
19714 # - multiply
19715 _Primitive-multiply-reg-by-reg:  # (payload primitive)
19716     0x11/imm32/alloc-id:fake:payload
19717     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
19718     0x11/imm32/alloc-id:fake
19719     _string-multiply/imm32/name
19720     0x11/imm32/alloc-id:fake
19721     Single-int-var-in-some-register/imm32/inouts
19722     0x11/imm32/alloc-id:fake
19723     Single-int-var-in-some-register/imm32/outputs
19724     0x11/imm32/alloc-id:fake
19725     _string_0f_af_multiply/imm32/subx-name
19726     1/imm32/rm32-is-first-inout
19727     3/imm32/r32-is-first-output
19728     0/imm32/no-imm32
19729     0/imm32/no-imm8
19730     0/imm32/no-disp32
19731     0/imm32/no-xm32
19732     0/imm32/no-x32
19733     0x11/imm32/alloc-id:fake
19734     _Primitive-multiply-reg-by-mem/imm32/next
19735 _Primitive-multiply-reg-by-mem:  # (payload primitive)
19736     0x11/imm32/alloc-id:fake:payload
19737     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
19738     0x11/imm32/alloc-id:fake
19739     _string-multiply/imm32/name
19740     0x11/imm32/alloc-id:fake
19741     Single-int-var-in-mem/imm32/inouts
19742     0x11/imm32/alloc-id:fake
19743     Single-int-var-in-some-register/imm32/outputs
19744     0x11/imm32/alloc-id:fake
19745     _string_0f_af_multiply/imm32/subx-name
19746     1/imm32/rm32-is-first-inout
19747     3/imm32/r32-is-first-output
19748     0/imm32/no-imm32
19749     0/imm32/no-imm8
19750     0/imm32/no-disp32
19751     0/imm32/no-xm32
19752     0/imm32/no-x32
19753     0x11/imm32/alloc-id:fake
19754     _Primitive-convert-mem-to-xreg/imm32/next
19755 # - convert int to floating point
19756 _Primitive-convert-mem-to-xreg:  # (payload primitive)
19757     0x11/imm32/alloc-id:fake:payload
19758     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
19759     0x11/imm32/alloc-id:fake
19760     _string-convert/imm32/name
19761     0x11/imm32/alloc-id:fake
19762     Single-int-var-in-mem/imm32/inouts
19763     0x11/imm32/alloc-id:fake
19764     Single-float-var-in-some-register/imm32/outputs
19765     0x11/imm32/alloc-id:fake
19766     _string_f3_0f_2a_convert_to_float/imm32/subx-name
19767     1/imm32/rm32-is-first-inout
19768     0/imm32/no-r32
19769     0/imm32/no-imm32
19770     0/imm32/no-imm8
19771     0/imm32/no-disp32
19772     0/imm32/no-xm32
19773     3/imm32/x32-is-first-output
19774     0x11/imm32/alloc-id:fake
19775     _Primitive-convert-reg-to-xreg/imm32/next
19776 _Primitive-convert-reg-to-xreg:  # (payload primitive)
19777     0x11/imm32/alloc-id:fake:payload
19778     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
19779     0x11/imm32/alloc-id:fake
19780     _string-convert/imm32/name
19781     0x11/imm32/alloc-id:fake
19782     Single-int-var-in-some-register/imm32/inouts
19783     0x11/imm32/alloc-id:fake
19784     Single-float-var-in-some-register/imm32/outputs
19785     0x11/imm32/alloc-id:fake
19786     _string_f3_0f_2a_convert_to_float/imm32/subx-name
19787     1/imm32/rm32-is-first-inout
19788     0/imm32/no-r32
19789     0/imm32/no-imm32
19790     0/imm32/no-imm8
19791     0/imm32/no-disp32
19792     0/imm32/no-xm32
19793     3/imm32/x32-is-first-output
19794     0x11/imm32/alloc-id:fake
19795     _Primitive-convert-xmem-to-reg/imm32/next
19796 # - convert floating point to int
19797 _Primitive-convert-xmem-to-reg:  # (payload primitive)
19798     0x11/imm32/alloc-id:fake:payload
19799     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
19800     0x11/imm32/alloc-id:fake
19801     _string-convert/imm32/name
19802     0x11/imm32/alloc-id:fake
19803     Single-float-var-in-mem/imm32/inouts
19804     0x11/imm32/alloc-id:fake
19805     Single-int-var-in-some-register/imm32/outputs
19806     0x11/imm32/alloc-id:fake
19807     _string_f3_0f_2d_convert_to_int/imm32/subx-name
19808     0/imm32/no-rm32
19809     3/imm32/r32-is-first-output
19810     0/imm32/no-imm32
19811     0/imm32/no-imm8
19812     0/imm32/no-disp32
19813     1/imm32/xm32-is-first-inout
19814     0/imm32/no-x32
19815     0x11/imm32/alloc-id:fake
19816     _Primitive-convert-xreg-to-reg/imm32/next
19817 _Primitive-convert-xreg-to-reg:  # (payload primitive)
19818     0x11/imm32/alloc-id:fake:payload
19819     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
19820     0x11/imm32/alloc-id:fake
19821     _string-convert/imm32/name
19822     0x11/imm32/alloc-id:fake
19823     Single-float-var-in-some-register/imm32/inouts
19824     0x11/imm32/alloc-id:fake
19825     Single-int-var-in-some-register/imm32/outputs
19826     0x11/imm32/alloc-id:fake
19827     _string_f3_0f_2d_convert_to_int/imm32/subx-name
19828     0/imm32/no-rm32
19829     3/imm32/r32-is-first-output
19830     0/imm32/no-imm32
19831     0/imm32/no-imm8
19832     0/imm32/no-disp32
19833     1/imm32/xm32-is-first-inout
19834     0/imm32/no-x32
19835     0x11/imm32/alloc-id:fake
19836     _Primitive-truncate-xmem-to-reg/imm32/next
19837 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
19838     0x11/imm32/alloc-id:fake:payload
19839     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
19840     0x11/imm32/alloc-id:fake
19841     _string-truncate/imm32/name
19842     0x11/imm32/alloc-id:fake
19843     Single-float-var-in-mem/imm32/inouts
19844     0x11/imm32/alloc-id:fake
19845     Single-int-var-in-some-register/imm32/outputs
19846     0x11/imm32/alloc-id:fake
19847     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
19848     0/imm32/no-rm32
19849     3/imm32/r32-is-first-output
19850     0/imm32/no-imm32
19851     0/imm32/no-imm8
19852     0/imm32/no-disp32
19853     1/imm32/xm32-is-first-inout
19854     0/imm32/no-x32
19855     0x11/imm32/alloc-id:fake
19856     _Primitive-truncate-xreg-to-reg/imm32/next
19857 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
19858     0x11/imm32/alloc-id:fake:payload
19859     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
19860     0x11/imm32/alloc-id:fake
19861     _string-truncate/imm32/name
19862     0x11/imm32/alloc-id:fake
19863     Single-float-var-in-some-register/imm32/inouts
19864     0x11/imm32/alloc-id:fake
19865     Single-int-var-in-some-register/imm32/outputs
19866     0x11/imm32/alloc-id:fake
19867     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
19868     0/imm32/no-rm32
19869     3/imm32/r32-is-first-output
19870     0/imm32/no-imm32
19871     0/imm32/no-imm8
19872     0/imm32/no-disp32
19873     1/imm32/xm32-is-first-inout
19874     0/imm32/no-x32
19875     0x11/imm32/alloc-id:fake
19876     _Primitive-reinterpret-xmem-as-reg/imm32/next
19877 # - reinterpret bytes (just for debugging)
19878 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
19879     0x11/imm32/alloc-id:fake:payload
19880     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
19881     0x11/imm32/alloc-id:fake
19882     _string-reinterpret/imm32/name
19883     0x11/imm32/alloc-id:fake
19884     Single-float-var-in-mem/imm32/inouts
19885     0x11/imm32/alloc-id:fake
19886     Single-int-var-in-some-register/imm32/outputs
19887     0x11/imm32/alloc-id:fake
19888     _string_8b_->/imm32/subx-name
19889     0/imm32/no-rm32
19890     3/imm32/r32-is-first-output
19891     0/imm32/no-imm32
19892     0/imm32/no-imm8
19893     0/imm32/no-disp32
19894     1/imm32/xm32-is-first-inout
19895     0/imm32/no-x32
19896     0x11/imm32/alloc-id:fake
19897     _Primitive-reinterpret-mem-as-xreg/imm32/next
19898 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
19899     0x11/imm32/alloc-id:fake:payload
19900     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
19901     0x11/imm32/alloc-id:fake
19902     _string-reinterpret/imm32/name
19903     0x11/imm32/alloc-id:fake
19904     Single-int-var-in-mem/imm32/inouts
19905     0x11/imm32/alloc-id:fake
19906     Single-float-var-in-some-register/imm32/outputs
19907     0x11/imm32/alloc-id:fake
19908     _string_f3_0f_10_copy/imm32/subx-name
19909     1/imm32/rm32-is-first-inout
19910     0/imm32/no-r32
19911     0/imm32/no-imm32
19912     0/imm32/no-imm8
19913     0/imm32/no-disp32
19914     0/imm32/no-xm32
19915     3/imm32/x32-is-first-output
19916     0x11/imm32/alloc-id:fake
19917     _Primitive-copy-xreg-to-xreg/imm32/next
19918 # - floating-point copy
19919 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
19920     0x11/imm32/alloc-id:fake:payload
19921     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
19922     0x11/imm32/alloc-id:fake
19923     _string-copy/imm32/name
19924     0x11/imm32/alloc-id:fake
19925     Single-float-var-in-some-register/imm32/inouts
19926     0x11/imm32/alloc-id:fake
19927     Single-float-var-in-some-register/imm32/outputs
19928     0x11/imm32/alloc-id:fake
19929     _string_f3_0f_11_copy/imm32/subx-name
19930     0/imm32/no-rm32
19931     0/imm32/no-r32
19932     0/imm32/no-imm32
19933     0/imm32/no-imm8
19934     0/imm32/no-disp32
19935     3/imm32/xm32-is-first-output
19936     1/imm32/x32-is-first-inout
19937     0x11/imm32/alloc-id:fake
19938     _Primitive-copy-xreg-to-mem/imm32/next
19939 _Primitive-copy-xreg-to-mem:  # (payload primitive)
19940     0x11/imm32/alloc-id:fake:payload
19941     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
19942     0x11/imm32/alloc-id:fake
19943     _string-copy-to/imm32/name
19944     0x11/imm32/alloc-id:fake
19945     Two-args-float-stack-float-reg/imm32/inouts
19946     0/imm32/no-outputs
19947     0/imm32/no-outputs
19948     0x11/imm32/alloc-id:fake
19949     _string_f3_0f_11_copy/imm32/subx-name
19950     0/imm32/no-rm32
19951     0/imm32/no-r32
19952     0/imm32/no-imm32
19953     0/imm32/no-imm8
19954     0/imm32/no-disp32
19955     1/imm32/xm32-is-first-inout
19956     2/imm32/x32-is-second-inout
19957     0x11/imm32/alloc-id:fake
19958     _Primitive-copy-mem-to-xreg/imm32/next
19959 _Primitive-copy-mem-to-xreg:  # (payload primitive)
19960     0x11/imm32/alloc-id:fake:payload
19961     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
19962     0x11/imm32/alloc-id:fake
19963     _string-copy/imm32/name
19964     0x11/imm32/alloc-id:fake
19965     Single-float-var-in-mem/imm32/inouts
19966     0x11/imm32/alloc-id:fake
19967     Single-float-var-in-some-register/imm32/outputs
19968     0x11/imm32/alloc-id:fake
19969     _string_f3_0f_10_copy/imm32/subx-name
19970     0/imm32/no-rm32
19971     0/imm32/no-r32
19972     0/imm32/no-imm32
19973     0/imm32/no-imm8
19974     0/imm32/no-disp32
19975     1/imm32/xm32-is-first-inout
19976     3/imm32/x32-is-first-output
19977     0x11/imm32/alloc-id:fake
19978     _Primitive-address-of-xmem/imm32/next
19979 # - floating-point-address
19980 _Primitive-address-of-xmem:  # (payload primitive)
19981     0x11/imm32/alloc-id:fake:payload
19982     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
19983     0x11/imm32/alloc-id:fake
19984     _string-address/imm32/name
19985     0x11/imm32/alloc-id:fake
19986     Single-float-var-in-mem/imm32/inouts
19987     0x11/imm32/alloc-id:fake
19988     Single-addr-var-in-some-register/imm32/outputs
19989     0x11/imm32/alloc-id:fake
19990     _string_8d_copy_address/imm32/subx-name
19991     1/imm32/rm32-is-first-inout
19992     3/imm32/r32-is-first-output
19993     0/imm32/no-imm32
19994     0/imm32/no-imm8
19995     0/imm32/no-disp32
19996     0/imm32/no-xm32
19997     0/imm32/no-x32
19998     0x11/imm32/alloc-id:fake
19999     _Primitive-add-xreg-to-xreg/imm32/next
20000 # - floating-point add
20001 _Primitive-add-xreg-to-xreg:  # (payload primitive)
20002     0x11/imm32/alloc-id:fake:payload
20003     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
20004     0x11/imm32/alloc-id:fake
20005     _string-add/imm32/name
20006     0x11/imm32/alloc-id:fake
20007     Single-float-var-in-some-register/imm32/inouts
20008     0x11/imm32/alloc-id:fake
20009     Single-float-var-in-some-register/imm32/outputs
20010     0x11/imm32/alloc-id:fake
20011     _string_f3_0f_58_add/imm32/subx-name
20012     0/imm32/no-rm32
20013     0/imm32/no-r32
20014     0/imm32/no-imm32
20015     0/imm32/no-imm8
20016     0/imm32/no-disp32
20017     1/imm32/xm32-is-first-inout
20018     3/imm32/x32-is-first-output
20019     0x11/imm32/alloc-id:fake
20020     _Primitive-add-mem-to-xreg/imm32/next
20021 _Primitive-add-mem-to-xreg:  # (payload primitive)
20022     0x11/imm32/alloc-id:fake:payload
20023     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
20024     0x11/imm32/alloc-id:fake
20025     _string-add/imm32/name
20026     0x11/imm32/alloc-id:fake
20027     Single-float-var-in-mem/imm32/inouts
20028     0x11/imm32/alloc-id:fake
20029     Single-float-var-in-some-register/imm32/outputs
20030     0x11/imm32/alloc-id:fake
20031     _string_f3_0f_58_add/imm32/subx-name
20032     0/imm32/no-rm32
20033     0/imm32/no-r32
20034     0/imm32/no-imm32
20035     0/imm32/no-imm8
20036     0/imm32/no-disp32
20037     1/imm32/xm32-is-first-inout
20038     3/imm32/x32-is-first-output
20039     0x11/imm32/alloc-id:fake
20040     _Primitive-subtract-xreg-from-xreg/imm32/next
20041 # - floating-point subtract
20042 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
20043     0x11/imm32/alloc-id:fake:payload
20044     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
20045     0x11/imm32/alloc-id:fake
20046     _string-subtract/imm32/name
20047     0x11/imm32/alloc-id:fake
20048     Single-float-var-in-some-register/imm32/inouts
20049     0x11/imm32/alloc-id:fake
20050     Single-float-var-in-some-register/imm32/outputs
20051     0x11/imm32/alloc-id:fake
20052     _string_f3_0f_5c_subtract/imm32/subx-name
20053     0/imm32/no-rm32
20054     0/imm32/no-r32
20055     0/imm32/no-imm32
20056     0/imm32/no-imm8
20057     0/imm32/no-disp32
20058     1/imm32/xm32-is-first-inout
20059     3/imm32/x32-is-first-output
20060     0x11/imm32/alloc-id:fake
20061     _Primitive-subtract-mem-from-xreg/imm32/next
20062 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
20063     0x11/imm32/alloc-id:fake:payload
20064     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
20065     0x11/imm32/alloc-id:fake
20066     _string-subtract/imm32/name
20067     0x11/imm32/alloc-id:fake
20068     Single-float-var-in-mem/imm32/inouts
20069     0x11/imm32/alloc-id:fake
20070     Single-float-var-in-some-register/imm32/outputs
20071     0x11/imm32/alloc-id:fake
20072     _string_f3_0f_5c_subtract/imm32/subx-name
20073     0/imm32/no-rm32
20074     0/imm32/no-r32
20075     0/imm32/no-imm32
20076     0/imm32/no-imm8
20077     0/imm32/no-disp32
20078     1/imm32/xm32-is-first-inout
20079     3/imm32/x32-is-first-output
20080     0x11/imm32/alloc-id:fake
20081     _Primitive-multiply-xreg-by-xreg/imm32/next
20082 # - floating-point multiply
20083 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
20084     0x11/imm32/alloc-id:fake:payload
20085     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
20086     0x11/imm32/alloc-id:fake
20087     _string-multiply/imm32/name
20088     0x11/imm32/alloc-id:fake
20089     Single-float-var-in-some-register/imm32/inouts
20090     0x11/imm32/alloc-id:fake
20091     Single-float-var-in-some-register/imm32/outputs
20092     0x11/imm32/alloc-id:fake
20093     _string_f3_0f_59_multiply/imm32/subx-name
20094     0/imm32/no-rm32
20095     0/imm32/no-r32
20096     0/imm32/no-imm32
20097     0/imm32/no-imm8
20098     0/imm32/no-disp32
20099     1/imm32/xm32-is-first-inout
20100     3/imm32/x32-is-first-output
20101     0x11/imm32/alloc-id:fake
20102     _Primitive-multiply-xreg-by-mem/imm32/next
20103 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
20104     0x11/imm32/alloc-id:fake:payload
20105     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
20106     0x11/imm32/alloc-id:fake
20107     _string-multiply/imm32/name
20108     0x11/imm32/alloc-id:fake
20109     Single-float-var-in-mem/imm32/inouts
20110     0x11/imm32/alloc-id:fake
20111     Single-float-var-in-some-register/imm32/outputs
20112     0x11/imm32/alloc-id:fake
20113     _string_f3_0f_59_multiply/imm32/subx-name
20114     0/imm32/no-rm32
20115     0/imm32/no-r32
20116     0/imm32/no-imm32
20117     0/imm32/no-imm8
20118     0/imm32/no-disp32
20119     1/imm32/xm32-is-first-inout
20120     3/imm32/x32-is-first-output
20121     0x11/imm32/alloc-id:fake
20122     _Primitive-divide-xreg-by-xreg/imm32/next
20123 # - floating-point divide
20124 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
20125     0x11/imm32/alloc-id:fake:payload
20126     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
20127     0x11/imm32/alloc-id:fake
20128     _string-divide/imm32/name
20129     0x11/imm32/alloc-id:fake
20130     Single-float-var-in-some-register/imm32/inouts
20131     0x11/imm32/alloc-id:fake
20132     Single-float-var-in-some-register/imm32/outputs
20133     0x11/imm32/alloc-id:fake
20134     _string_f3_0f_5e_divide/imm32/subx-name
20135     0/imm32/no-rm32
20136     0/imm32/no-r32
20137     0/imm32/no-imm32
20138     0/imm32/no-imm8
20139     0/imm32/no-disp32
20140     1/imm32/xm32-is-first-inout
20141     3/imm32/x32-is-first-output
20142     0x11/imm32/alloc-id:fake
20143     _Primitive-divide-xreg-by-mem/imm32/next
20144 _Primitive-divide-xreg-by-mem:  # (payload primitive)
20145     0x11/imm32/alloc-id:fake:payload
20146     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
20147     0x11/imm32/alloc-id:fake
20148     _string-divide/imm32/name
20149     0x11/imm32/alloc-id:fake
20150     Single-float-var-in-mem/imm32/inouts
20151     0x11/imm32/alloc-id:fake
20152     Single-float-var-in-some-register/imm32/outputs
20153     0x11/imm32/alloc-id:fake
20154     _string_f3_0f_5e_divide/imm32/subx-name
20155     0/imm32/no-rm32
20156     0/imm32/no-r32
20157     0/imm32/no-imm32
20158     0/imm32/no-imm8
20159     0/imm32/no-disp32
20160     1/imm32/xm32-is-first-inout
20161     3/imm32/x32-is-first-output
20162     0x11/imm32/alloc-id:fake
20163     _Primitive-max-xreg-with-xreg/imm32/next
20164 # - floating-point maximum
20165 _Primitive-max-xreg-with-xreg:  # (payload primitive)
20166     0x11/imm32/alloc-id:fake:payload
20167     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
20168     0x11/imm32/alloc-id:fake
20169     _string-max/imm32/name
20170     0x11/imm32/alloc-id:fake
20171     Single-float-var-in-some-register/imm32/inouts
20172     0x11/imm32/alloc-id:fake
20173     Single-float-var-in-some-register/imm32/outputs
20174     0x11/imm32/alloc-id:fake
20175     _string_f3_0f_5f_max/imm32/subx-name
20176     0/imm32/no-rm32
20177     0/imm32/no-r32
20178     0/imm32/no-imm32
20179     0/imm32/no-imm8
20180     0/imm32/no-disp32
20181     1/imm32/xm32-is-first-inout
20182     3/imm32/x32-is-first-output
20183     0x11/imm32/alloc-id:fake
20184     _Primitive-max-xreg-with-mem/imm32/next
20185 _Primitive-max-xreg-with-mem:  # (payload primitive)
20186     0x11/imm32/alloc-id:fake:payload
20187     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
20188     0x11/imm32/alloc-id:fake
20189     _string-max/imm32/name
20190     0x11/imm32/alloc-id:fake
20191     Single-float-var-in-mem/imm32/inouts
20192     0x11/imm32/alloc-id:fake
20193     Single-float-var-in-some-register/imm32/outputs
20194     0x11/imm32/alloc-id:fake
20195     _string_f3_0f_5f_max/imm32/subx-name
20196     0/imm32/no-rm32
20197     0/imm32/no-r32
20198     0/imm32/no-imm32
20199     0/imm32/no-imm8
20200     0/imm32/no-disp32
20201     1/imm32/xm32-is-first-inout
20202     3/imm32/x32-is-first-output
20203     0x11/imm32/alloc-id:fake
20204     _Primitive-min-xreg-with-xreg/imm32/next
20205 # - floating-point minimum
20206 _Primitive-min-xreg-with-xreg:  # (payload primitive)
20207     0x11/imm32/alloc-id:fake:payload
20208     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
20209     0x11/imm32/alloc-id:fake
20210     _string-min/imm32/name
20211     0x11/imm32/alloc-id:fake
20212     Single-float-var-in-some-register/imm32/inouts
20213     0x11/imm32/alloc-id:fake
20214     Single-float-var-in-some-register/imm32/outputs
20215     0x11/imm32/alloc-id:fake
20216     _string_f3_0f_5d_min/imm32/subx-name
20217     0/imm32/no-rm32
20218     0/imm32/no-r32
20219     0/imm32/no-imm32
20220     0/imm32/no-imm8
20221     0/imm32/no-disp32
20222     1/imm32/xm32-is-first-inout
20223     3/imm32/x32-is-first-output
20224     0x11/imm32/alloc-id:fake
20225     _Primitive-min-xreg-with-mem/imm32/next
20226 _Primitive-min-xreg-with-mem:  # (payload primitive)
20227     0x11/imm32/alloc-id:fake:payload
20228     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
20229     0x11/imm32/alloc-id:fake
20230     _string-min/imm32/name
20231     0x11/imm32/alloc-id:fake
20232     Single-float-var-in-mem/imm32/inouts
20233     0x11/imm32/alloc-id:fake
20234     Single-float-var-in-some-register/imm32/outputs
20235     0x11/imm32/alloc-id:fake
20236     _string_f3_0f_5d_min/imm32/subx-name
20237     0/imm32/no-rm32
20238     0/imm32/no-r32
20239     0/imm32/no-imm32
20240     0/imm32/no-imm8
20241     0/imm32/no-disp32
20242     1/imm32/xm32-is-first-inout
20243     3/imm32/x32-is-first-output
20244     0x11/imm32/alloc-id:fake
20245     _Primitive-reciprocal-xreg-to-xreg/imm32/next
20246 # - floating-point reciprocal
20247 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
20248     0x11/imm32/alloc-id:fake:payload
20249     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
20250     0x11/imm32/alloc-id:fake
20251     _string-reciprocal/imm32/name
20252     0x11/imm32/alloc-id:fake
20253     Single-float-var-in-some-register/imm32/inouts
20254     0x11/imm32/alloc-id:fake
20255     Single-float-var-in-some-register/imm32/outputs
20256     0x11/imm32/alloc-id:fake
20257     _string_f3_0f_53_reciprocal/imm32/subx-name
20258     0/imm32/no-rm32
20259     0/imm32/no-r32
20260     0/imm32/no-imm32
20261     0/imm32/no-imm8
20262     0/imm32/no-disp32
20263     1/imm32/xm32-is-first-inout
20264     3/imm32/x32-is-first-output
20265     0x11/imm32/alloc-id:fake
20266     _Primitive-reciprocal-mem-to-xreg/imm32/next
20267 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
20268     0x11/imm32/alloc-id:fake:payload
20269     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
20270     0x11/imm32/alloc-id:fake
20271     _string-reciprocal/imm32/name
20272     0x11/imm32/alloc-id:fake
20273     Single-float-var-in-mem/imm32/inouts
20274     0x11/imm32/alloc-id:fake
20275     Single-float-var-in-some-register/imm32/outputs
20276     0x11/imm32/alloc-id:fake
20277     _string_f3_0f_53_reciprocal/imm32/subx-name
20278     0/imm32/no-rm32
20279     0/imm32/no-r32
20280     0/imm32/no-imm32
20281     0/imm32/no-imm8
20282     0/imm32/no-disp32
20283     1/imm32/xm32-is-first-inout
20284     3/imm32/x32-is-first-output
20285     0x11/imm32/alloc-id:fake
20286     _Primitive-square-root-xreg-to-xreg/imm32/next
20287 # - floating-point square root
20288 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
20289     0x11/imm32/alloc-id:fake:payload
20290     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
20291     0x11/imm32/alloc-id:fake
20292     _string-square-root/imm32/name
20293     0x11/imm32/alloc-id:fake
20294     Single-float-var-in-some-register/imm32/inouts
20295     0x11/imm32/alloc-id:fake
20296     Single-float-var-in-some-register/imm32/outputs
20297     0x11/imm32/alloc-id:fake
20298     _string_f3_0f_51_square_root/imm32/subx-name
20299     0/imm32/no-rm32
20300     0/imm32/no-r32
20301     0/imm32/no-imm32
20302     0/imm32/no-imm8
20303     0/imm32/no-disp32
20304     1/imm32/xm32-is-first-inout
20305     3/imm32/x32-is-first-output
20306     0x11/imm32/alloc-id:fake
20307     _Primitive-square-root-mem-to-xreg/imm32/next
20308 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
20309     0x11/imm32/alloc-id:fake:payload
20310     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
20311     0x11/imm32/alloc-id:fake
20312     _string-square-root/imm32/name
20313     0x11/imm32/alloc-id:fake
20314     Single-float-var-in-mem/imm32/inouts
20315     0x11/imm32/alloc-id:fake
20316     Single-float-var-in-some-register/imm32/outputs
20317     0x11/imm32/alloc-id:fake
20318     _string_f3_0f_51_square_root/imm32/subx-name
20319     0/imm32/no-rm32
20320     0/imm32/no-r32
20321     0/imm32/no-imm32
20322     0/imm32/no-imm8
20323     0/imm32/no-disp32
20324     1/imm32/xm32-is-first-inout
20325     3/imm32/x32-is-first-output
20326     0x11/imm32/alloc-id:fake
20327     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
20328 # - floating-point inverse square root 1/sqrt(x)
20329 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
20330     0x11/imm32/alloc-id:fake:payload
20331     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
20332     0x11/imm32/alloc-id:fake
20333     _string-inverse-square-root/imm32/name
20334     0x11/imm32/alloc-id:fake
20335     Single-float-var-in-some-register/imm32/inouts
20336     0x11/imm32/alloc-id:fake
20337     Single-float-var-in-some-register/imm32/outputs
20338     0x11/imm32/alloc-id:fake
20339     _string_f3_0f_52_inverse_square_root/imm32/subx-name
20340     0/imm32/no-rm32
20341     0/imm32/no-r32
20342     0/imm32/no-imm32
20343     0/imm32/no-imm8
20344     0/imm32/no-disp32
20345     1/imm32/xm32-is-first-inout
20346     3/imm32/x32-is-first-output
20347     0x11/imm32/alloc-id:fake
20348     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
20349 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
20350     0x11/imm32/alloc-id:fake:payload
20351     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
20352     0x11/imm32/alloc-id:fake
20353     _string-inverse-square-root/imm32/name
20354     0x11/imm32/alloc-id:fake
20355     Single-float-var-in-mem/imm32/inouts
20356     0x11/imm32/alloc-id:fake
20357     Single-float-var-in-some-register/imm32/outputs
20358     0x11/imm32/alloc-id:fake
20359     _string_f3_0f_52_inverse_square_root/imm32/subx-name
20360     0/imm32/no-rm32
20361     0/imm32/no-r32
20362     0/imm32/no-imm32
20363     0/imm32/no-imm8
20364     0/imm32/no-disp32
20365     1/imm32/xm32-is-first-inout
20366     3/imm32/x32-is-first-output
20367     0x11/imm32/alloc-id:fake
20368     _Primitive-compare-xreg-with-xreg/imm32/next
20369 # - floating-point compare
20370 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
20371     0x11/imm32/alloc-id:fake:payload
20372     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
20373     0x11/imm32/alloc-id:fake
20374     _string-compare/imm32/name
20375     0x11/imm32/alloc-id:fake
20376     Two-float-args-in-regs/imm32/inouts
20377     0/imm32/no-outputs
20378     0/imm32/no-outputs
20379     0x11/imm32/alloc-id:fake
20380     _string_0f_2f_compare/imm32/subx-name
20381     0/imm32/no-rm32
20382     0/imm32/no-r32
20383     0/imm32/no-imm32
20384     0/imm32/no-imm8
20385     0/imm32/no-disp32
20386     1/imm32/xm32-is-first-inout
20387     2/imm32/x32-is-second-inout
20388     0x11/imm32/alloc-id:fake
20389     _Primitive-compare-xreg-with-mem/imm32/next
20390 _Primitive-compare-xreg-with-mem:  # (payload primitive)
20391     0x11/imm32/alloc-id:fake:payload
20392     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
20393     0x11/imm32/alloc-id:fake
20394     _string-compare/imm32/name
20395     0x11/imm32/alloc-id:fake
20396     Two-args-float-reg-float-stack/imm32/inouts
20397     0/imm32/no-outputs
20398     0/imm32/no-outputs
20399     0x11/imm32/alloc-id:fake
20400     _string_0f_2f_compare/imm32/subx-name
20401     0/imm32/no-rm32
20402     0/imm32/no-r32
20403     0/imm32/no-imm32
20404     0/imm32/no-imm8
20405     0/imm32/no-disp32
20406     2/imm32/xm32-is-second-inout
20407     1/imm32/x32-is-first-inout
20408     0x11/imm32/alloc-id:fake
20409     _Primitive-break-if-addr</imm32/next
20410 # - branches
20411 _Primitive-break-if-addr<:  # (payload primitive)
20412     0x11/imm32/alloc-id:fake:payload
20413     0x11/imm32/alloc-id:fake
20414     _string-break-if-addr</imm32/name
20415     0/imm32/no-inouts
20416     0/imm32/no-inouts
20417     0/imm32/no-outputs
20418     0/imm32/no-outputs
20419     0x11/imm32/alloc-id:fake
20420     _string_0f_82_jump_break/imm32/subx-name
20421     0/imm32/no-rm32
20422     0/imm32/no-r32
20423     0/imm32/no-imm32
20424     0/imm32/no-imm8
20425     0/imm32/no-disp32
20426     0/imm32/no-xm32
20427     0/imm32/no-x32
20428     0x11/imm32/alloc-id:fake
20429     _Primitive-break-if-addr>=/imm32/next
20430 _Primitive-break-if-addr>=:  # (payload primitive)
20431     0x11/imm32/alloc-id:fake:payload
20432     0x11/imm32/alloc-id:fake
20433     _string-break-if-addr>=/imm32/name
20434     0/imm32/no-inouts
20435     0/imm32/no-inouts
20436     0/imm32/no-outputs
20437     0/imm32/no-outputs
20438     0x11/imm32/alloc-id:fake
20439     _string_0f_83_jump_break/imm32/subx-name
20440     0/imm32/no-rm32
20441     0/imm32/no-r32
20442     0/imm32/no-imm32
20443     0/imm32/no-imm8
20444     0/imm32/no-disp32
20445     0/imm32/no-xm32
20446     0/imm32/no-x32
20447     0x11/imm32/alloc-id:fake
20448     _Primitive-break-if-=/imm32/next
20449 _Primitive-break-if-=:  # (payload primitive)
20450     0x11/imm32/alloc-id:fake:payload
20451     0x11/imm32/alloc-id:fake
20452     _string-break-if-=/imm32/name
20453     0/imm32/no-inouts
20454     0/imm32/no-inouts
20455     0/imm32/no-outputs
20456     0/imm32/no-outputs
20457     0x11/imm32/alloc-id:fake
20458     _string_0f_84_jump_break/imm32/subx-name
20459     0/imm32/no-rm32
20460     0/imm32/no-r32
20461     0/imm32/no-imm32
20462     0/imm32/no-imm8
20463     0/imm32/no-disp32
20464     0/imm32/no-xm32
20465     0/imm32/no-x32
20466     0x11/imm32/alloc-id:fake
20467     _Primitive-break-if-!=/imm32/next
20468 _Primitive-break-if-!=:  # (payload primitive)
20469     0x11/imm32/alloc-id:fake:payload
20470     0x11/imm32/alloc-id:fake
20471     _string-break-if-!=/imm32/name
20472     0/imm32/no-inouts
20473     0/imm32/no-inouts
20474     0/imm32/no-outputs
20475     0/imm32/no-outputs
20476     0x11/imm32/alloc-id:fake
20477     _string_0f_85_jump_break/imm32/subx-name
20478     0/imm32/no-rm32
20479     0/imm32/no-r32
20480     0/imm32/no-imm32
20481     0/imm32/no-imm8
20482     0/imm32/no-disp32
20483     0/imm32/no-xm32
20484     0/imm32/no-x32
20485     0x11/imm32/alloc-id:fake
20486     _Primitive-break-if-addr<=/imm32/next
20487 _Primitive-break-if-addr<=:  # (payload primitive)
20488     0x11/imm32/alloc-id:fake:payload
20489     0x11/imm32/alloc-id:fake
20490     _string-break-if-addr<=/imm32/name
20491     0/imm32/no-inouts
20492     0/imm32/no-inouts
20493     0/imm32/no-outputs
20494     0/imm32/no-outputs
20495     0x11/imm32/alloc-id:fake
20496     _string_0f_86_jump_break/imm32/subx-name
20497     0/imm32/no-rm32
20498     0/imm32/no-r32
20499     0/imm32/no-imm32
20500     0/imm32/no-imm8
20501     0/imm32/no-disp32
20502     0/imm32/no-xm32
20503     0/imm32/no-x32
20504     0x11/imm32/alloc-id:fake
20505     _Primitive-break-if-addr>/imm32/next
20506 _Primitive-break-if-addr>:  # (payload primitive)
20507     0x11/imm32/alloc-id:fake:payload
20508     0x11/imm32/alloc-id:fake
20509     _string-break-if-addr>/imm32/name
20510     0/imm32/no-inouts
20511     0/imm32/no-inouts
20512     0/imm32/no-outputs
20513     0/imm32/no-outputs
20514     0x11/imm32/alloc-id:fake
20515     _string_0f_87_jump_break/imm32/subx-name
20516     0/imm32/no-rm32
20517     0/imm32/no-r32
20518     0/imm32/no-imm32
20519     0/imm32/no-imm8
20520     0/imm32/no-disp32
20521     0/imm32/no-xm32
20522     0/imm32/no-x32
20523     0x11/imm32/alloc-id:fake
20524     _Primitive-break-if-</imm32/next
20525 _Primitive-break-if-<:  # (payload primitive)
20526     0x11/imm32/alloc-id:fake:payload
20527     0x11/imm32/alloc-id:fake
20528     _string-break-if-</imm32/name
20529     0/imm32/no-inouts
20530     0/imm32/no-inouts
20531     0/imm32/no-outputs
20532     0/imm32/no-outputs
20533     0x11/imm32/alloc-id:fake
20534     _string_0f_8c_jump_break/imm32/subx-name
20535     0/imm32/no-rm32
20536     0/imm32/no-r32
20537     0/imm32/no-imm32
20538     0/imm32/no-imm8
20539     0/imm32/no-disp32
20540     0/imm32/no-xm32
20541     0/imm32/no-x32
20542     0x11/imm32/alloc-id:fake
20543     _Primitive-break-if->=/imm32/next
20544 _Primitive-break-if->=:  # (payload primitive)
20545     0x11/imm32/alloc-id:fake:payload
20546     0x11/imm32/alloc-id:fake
20547     _string-break-if->=/imm32/name
20548     0/imm32/no-inouts
20549     0/imm32/no-inouts
20550     0/imm32/no-outputs
20551     0/imm32/no-outputs
20552     0x11/imm32/alloc-id:fake
20553     _string_0f_8d_jump_break/imm32/subx-name
20554     0/imm32/no-rm32
20555     0/imm32/no-r32
20556     0/imm32/no-imm32
20557     0/imm32/no-imm8
20558     0/imm32/no-disp32
20559     0/imm32/no-xm32
20560     0/imm32/no-x32
20561     0x11/imm32/alloc-id:fake
20562     _Primitive-break-if-<=/imm32/next
20563 _Primitive-break-if-<=:  # (payload primitive)
20564     0x11/imm32/alloc-id:fake:payload
20565     0x11/imm32/alloc-id:fake
20566     _string-break-if-<=/imm32/name
20567     0/imm32/no-inouts
20568     0/imm32/no-inouts
20569     0/imm32/no-outputs
20570     0/imm32/no-outputs
20571     0x11/imm32/alloc-id:fake
20572     _string_0f_8e_jump_break/imm32/subx-name
20573     0/imm32/no-rm32
20574     0/imm32/no-r32
20575     0/imm32/no-imm32
20576     0/imm32/no-imm8
20577     0/imm32/no-disp32
20578     0/imm32/no-xm32
20579     0/imm32/no-x32
20580     0x11/imm32/alloc-id:fake
20581     _Primitive-break-if->/imm32/next
20582 _Primitive-break-if->:  # (payload primitive)
20583     0x11/imm32/alloc-id:fake:payload
20584     0x11/imm32/alloc-id:fake
20585     _string-break-if->/imm32/name
20586     0/imm32/no-inouts
20587     0/imm32/no-inouts
20588     0/imm32/no-outputs
20589     0/imm32/no-outputs
20590     0x11/imm32/alloc-id:fake
20591     _string_0f_8f_jump_break/imm32/subx-name
20592     0/imm32/no-rm32
20593     0/imm32/no-r32
20594     0/imm32/no-imm32
20595     0/imm32/no-imm8
20596     0/imm32/no-disp32
20597     0/imm32/no-xm32
20598     0/imm32/no-x32
20599     0x11/imm32/alloc-id:fake
20600     _Primitive-break/imm32/next
20601 _Primitive-break:  # (payload primitive)
20602     0x11/imm32/alloc-id:fake:payload
20603     0x11/imm32/alloc-id:fake
20604     _string-break/imm32/name
20605     0/imm32/no-inouts
20606     0/imm32/no-inouts
20607     0/imm32/no-outputs
20608     0/imm32/no-outputs
20609     0x11/imm32/alloc-id:fake
20610     _string_e9_jump_break/imm32/subx-name
20611     0/imm32/no-rm32
20612     0/imm32/no-r32
20613     0/imm32/no-imm32
20614     0/imm32/no-imm8
20615     0/imm32/no-disp32
20616     0/imm32/no-xm32
20617     0/imm32/no-x32
20618     0x11/imm32/alloc-id:fake
20619     _Primitive-loop-if-addr</imm32/next
20620 _Primitive-loop-if-addr<:  # (payload primitive)
20621     0x11/imm32/alloc-id:fake:payload
20622     0x11/imm32/alloc-id:fake
20623     _string-loop-if-addr</imm32/name
20624     0/imm32/no-inouts
20625     0/imm32/no-inouts
20626     0/imm32/no-outputs
20627     0/imm32/no-outputs
20628     0x11/imm32/alloc-id:fake
20629     _string_0f_82_jump_loop/imm32/subx-name
20630     0/imm32/no-rm32
20631     0/imm32/no-r32
20632     0/imm32/no-imm32
20633     0/imm32/no-imm8
20634     0/imm32/no-disp32
20635     0/imm32/no-xm32
20636     0/imm32/no-x32
20637     0x11/imm32/alloc-id:fake
20638     _Primitive-loop-if-addr>=/imm32/next
20639 _Primitive-loop-if-addr>=:  # (payload primitive)
20640     0x11/imm32/alloc-id:fake:payload
20641     0x11/imm32/alloc-id:fake
20642     _string-loop-if-addr>=/imm32/name
20643     0/imm32/no-inouts
20644     0/imm32/no-inouts
20645     0/imm32/no-outputs
20646     0/imm32/no-outputs
20647     0x11/imm32/alloc-id:fake
20648     _string_0f_83_jump_loop/imm32/subx-name
20649     0/imm32/no-rm32
20650     0/imm32/no-r32
20651     0/imm32/no-imm32
20652     0/imm32/no-imm8
20653     0/imm32/no-disp32
20654     0/imm32/no-xm32
20655     0/imm32/no-x32
20656     0x11/imm32/alloc-id:fake
20657     _Primitive-loop-if-=/imm32/next
20658 _Primitive-loop-if-=:  # (payload primitive)
20659     0x11/imm32/alloc-id:fake:payload
20660     0x11/imm32/alloc-id:fake
20661     _string-loop-if-=/imm32/name
20662     0/imm32/no-inouts
20663     0/imm32/no-inouts
20664     0/imm32/no-outputs
20665     0/imm32/no-outputs
20666     0x11/imm32/alloc-id:fake
20667     _string_0f_84_jump_loop/imm32/subx-name
20668     0/imm32/no-rm32
20669     0/imm32/no-r32
20670     0/imm32/no-imm32
20671     0/imm32/no-imm8
20672     0/imm32/no-disp32
20673     0/imm32/no-xm32
20674     0/imm32/no-x32
20675     0x11/imm32/alloc-id:fake
20676     _Primitive-loop-if-!=/imm32/next
20677 _Primitive-loop-if-!=:  # (payload primitive)
20678     0x11/imm32/alloc-id:fake:payload
20679     0x11/imm32/alloc-id:fake
20680     _string-loop-if-!=/imm32/name
20681     0/imm32/no-inouts
20682     0/imm32/no-inouts
20683     0/imm32/no-outputs
20684     0/imm32/no-outputs
20685     0x11/imm32/alloc-id:fake
20686     _string_0f_85_jump_loop/imm32/subx-name
20687     0/imm32/no-rm32
20688     0/imm32/no-r32
20689     0/imm32/no-imm32
20690     0/imm32/no-imm8
20691     0/imm32/no-disp32
20692     0/imm32/no-xm32
20693     0/imm32/no-x32
20694     0x11/imm32/alloc-id:fake
20695     _Primitive-loop-if-addr<=/imm32/next
20696 _Primitive-loop-if-addr<=:  # (payload primitive)
20697     0x11/imm32/alloc-id:fake:payload
20698     0x11/imm32/alloc-id:fake
20699     _string-loop-if-addr<=/imm32/name
20700     0/imm32/no-inouts
20701     0/imm32/no-inouts
20702     0/imm32/no-outputs
20703     0/imm32/no-outputs
20704     0x11/imm32/alloc-id:fake
20705     _string_0f_86_jump_loop/imm32/subx-name
20706     0/imm32/no-rm32
20707     0/imm32/no-r32
20708     0/imm32/no-imm32
20709     0/imm32/no-imm8
20710     0/imm32/no-disp32
20711     0/imm32/no-xm32
20712     0/imm32/no-x32
20713     0x11/imm32/alloc-id:fake
20714     _Primitive-loop-if-addr>/imm32/next
20715 _Primitive-loop-if-addr>:  # (payload primitive)
20716     0x11/imm32/alloc-id:fake:payload
20717     0x11/imm32/alloc-id:fake
20718     _string-loop-if-addr>/imm32/name
20719     0/imm32/no-inouts
20720     0/imm32/no-inouts
20721     0/imm32/no-outputs
20722     0/imm32/no-outputs
20723     0x11/imm32/alloc-id:fake
20724     _string_0f_87_jump_loop/imm32/subx-name
20725     0/imm32/no-rm32
20726     0/imm32/no-r32
20727     0/imm32/no-imm32
20728     0/imm32/no-imm8
20729     0/imm32/no-disp32
20730     0/imm32/no-xm32
20731     0/imm32/no-x32
20732     0x11/imm32/alloc-id:fake
20733     _Primitive-loop-if-</imm32/next
20734 _Primitive-loop-if-<:  # (payload primitive)
20735     0x11/imm32/alloc-id:fake:payload
20736     0x11/imm32/alloc-id:fake
20737     _string-loop-if-</imm32/name
20738     0/imm32/no-inouts
20739     0/imm32/no-inouts
20740     0/imm32/no-outputs
20741     0/imm32/no-outputs
20742     0x11/imm32/alloc-id:fake
20743     _string_0f_8c_jump_loop/imm32/subx-name
20744     0/imm32/no-rm32
20745     0/imm32/no-r32
20746     0/imm32/no-imm32
20747     0/imm32/no-imm8
20748     0/imm32/no-disp32
20749     0/imm32/no-xm32
20750     0/imm32/no-x32
20751     0x11/imm32/alloc-id:fake
20752     _Primitive-loop-if->=/imm32/next
20753 _Primitive-loop-if->=:  # (payload primitive)
20754     0x11/imm32/alloc-id:fake:payload
20755     0x11/imm32/alloc-id:fake
20756     _string-loop-if->=/imm32/name
20757     0/imm32/no-inouts
20758     0/imm32/no-inouts
20759     0/imm32/no-outputs
20760     0/imm32/no-outputs
20761     0x11/imm32/alloc-id:fake
20762     _string_0f_8d_jump_loop/imm32/subx-name
20763     0/imm32/no-rm32
20764     0/imm32/no-r32
20765     0/imm32/no-imm32
20766     0/imm32/no-imm8
20767     0/imm32/no-disp32
20768     0/imm32/no-xm32
20769     0/imm32/no-x32
20770     0x11/imm32/alloc-id:fake
20771     _Primitive-loop-if-<=/imm32/next
20772 _Primitive-loop-if-<=:  # (payload primitive)
20773     0x11/imm32/alloc-id:fake:payload
20774     0x11/imm32/alloc-id:fake
20775     _string-loop-if-<=/imm32/name
20776     0/imm32/no-inouts
20777     0/imm32/no-inouts
20778     0/imm32/no-outputs
20779     0/imm32/no-outputs
20780     0x11/imm32/alloc-id:fake
20781     _string_0f_8e_jump_loop/imm32/subx-name
20782     0/imm32/no-rm32
20783     0/imm32/no-r32
20784     0/imm32/no-imm32
20785     0/imm32/no-imm8
20786     0/imm32/no-disp32
20787     0/imm32/no-xm32
20788     0/imm32/no-x32
20789     0x11/imm32/alloc-id:fake
20790     _Primitive-loop-if->/imm32/next
20791 _Primitive-loop-if->:  # (payload primitive)
20792     0x11/imm32/alloc-id:fake:payload
20793     0x11/imm32/alloc-id:fake
20794     _string-loop-if->/imm32/name
20795     0/imm32/no-inouts
20796     0/imm32/no-inouts
20797     0/imm32/no-outputs
20798     0/imm32/no-outputs
20799     0x11/imm32/alloc-id:fake
20800     _string_0f_8f_jump_loop/imm32/subx-name
20801     0/imm32/no-rm32
20802     0/imm32/no-r32
20803     0/imm32/no-imm32
20804     0/imm32/no-imm8
20805     0/imm32/no-disp32
20806     0/imm32/no-xm32
20807     0/imm32/no-x32
20808     0x11/imm32/alloc-id:fake
20809     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
20810 _Primitive-loop:  # (payload primitive)
20811     0x11/imm32/alloc-id:fake:payload
20812     0x11/imm32/alloc-id:fake
20813     _string-loop/imm32/name
20814     0/imm32/no-inouts
20815     0/imm32/no-inouts
20816     0/imm32/no-outputs
20817     0/imm32/no-outputs
20818     0x11/imm32/alloc-id:fake
20819     _string_e9_jump_loop/imm32/subx-name
20820     0/imm32/no-rm32
20821     0/imm32/no-r32
20822     0/imm32/no-imm32
20823     0/imm32/no-imm8
20824     0/imm32/no-disp32
20825     0/imm32/no-xm32
20826     0/imm32/no-x32
20827     0x11/imm32/alloc-id:fake
20828     _Primitive-break-if-addr<-named/imm32/next
20829 # - branches to named blocks
20830 _Primitive-break-if-addr<-named:  # (payload primitive)
20831     0x11/imm32/alloc-id:fake:payload
20832     0x11/imm32/alloc-id:fake
20833     _string-break-if-addr</imm32/name
20834     0x11/imm32/alloc-id:fake
20835     Single-lit-var/imm32/inouts
20836     0/imm32/no-outputs
20837     0/imm32/no-outputs
20838     0x11/imm32/alloc-id:fake
20839     _string_0f_82_jump_label/imm32/subx-name
20840     0/imm32/no-rm32
20841     0/imm32/no-r32
20842     0/imm32/no-imm32
20843     0/imm32/no-imm8
20844     1/imm32/disp32-is-first-inout
20845     0/imm32/no-xm32
20846     0/imm32/no-x32
20847     0x11/imm32/alloc-id:fake
20848     _Primitive-break-if-addr>=-named/imm32/next
20849 _Primitive-break-if-addr>=-named:  # (payload primitive)
20850     0x11/imm32/alloc-id:fake:payload
20851     0x11/imm32/alloc-id:fake
20852     _string-break-if-addr>=/imm32/name
20853     0x11/imm32/alloc-id:fake
20854     Single-lit-var/imm32/inouts
20855     0/imm32/no-outputs
20856     0/imm32/no-outputs
20857     0x11/imm32/alloc-id:fake
20858     _string_0f_83_jump_label/imm32/subx-name
20859     0/imm32/no-rm32
20860     0/imm32/no-r32
20861     0/imm32/no-imm32
20862     0/imm32/no-imm8
20863     1/imm32/disp32-is-first-inout
20864     0/imm32/no-xm32
20865     0/imm32/no-x32
20866     0x11/imm32/alloc-id:fake
20867     _Primitive-break-if-=-named/imm32/next
20868 _Primitive-break-if-=-named:  # (payload primitive)
20869     0x11/imm32/alloc-id:fake:payload
20870     0x11/imm32/alloc-id:fake
20871     _string-break-if-=/imm32/name
20872     0x11/imm32/alloc-id:fake
20873     Single-lit-var/imm32/inouts
20874     0/imm32/no-outputs
20875     0/imm32/no-outputs
20876     0x11/imm32/alloc-id:fake
20877     _string_0f_84_jump_label/imm32/subx-name
20878     0/imm32/no-rm32
20879     0/imm32/no-r32
20880     0/imm32/no-imm32
20881     0/imm32/no-imm8
20882     1/imm32/disp32-is-first-inout
20883     0/imm32/no-xm32
20884     0/imm32/no-x32
20885     0x11/imm32/alloc-id:fake
20886     _Primitive-break-if-!=-named/imm32/next
20887 _Primitive-break-if-!=-named:  # (payload primitive)
20888     0x11/imm32/alloc-id:fake:payload
20889     0x11/imm32/alloc-id:fake
20890     _string-break-if-!=/imm32/name
20891     0x11/imm32/alloc-id:fake
20892     Single-lit-var/imm32/inouts
20893     0/imm32/no-outputs
20894     0/imm32/no-outputs
20895     0x11/imm32/alloc-id:fake
20896     _string_0f_85_jump_label/imm32/subx-name
20897     0/imm32/no-rm32
20898     0/imm32/no-r32
20899     0/imm32/no-imm32
20900     0/imm32/no-imm8
20901     1/imm32/disp32-is-first-inout
20902     0/imm32/no-xm32
20903     0/imm32/no-x32
20904     0x11/imm32/alloc-id:fake
20905     _Primitive-break-if-addr<=-named/imm32/next
20906 _Primitive-break-if-addr<=-named:  # (payload primitive)
20907     0x11/imm32/alloc-id:fake:payload
20908     0x11/imm32/alloc-id:fake
20909     _string-break-if-addr<=/imm32/name
20910     0x11/imm32/alloc-id:fake
20911     Single-lit-var/imm32/inouts
20912     0/imm32/no-outputs
20913     0/imm32/no-outputs
20914     0x11/imm32/alloc-id:fake
20915     _string_0f_86_jump_label/imm32/subx-name
20916     0/imm32/no-rm32
20917     0/imm32/no-r32
20918     0/imm32/no-imm32
20919     0/imm32/no-imm8
20920     1/imm32/disp32-is-first-inout
20921     0/imm32/no-xm32
20922     0/imm32/no-x32
20923     0x11/imm32/alloc-id:fake
20924     _Primitive-break-if-addr>-named/imm32/next
20925 _Primitive-break-if-addr>-named:  # (payload primitive)
20926     0x11/imm32/alloc-id:fake:payload
20927     0x11/imm32/alloc-id:fake
20928     _string-break-if-addr>/imm32/name
20929     0x11/imm32/alloc-id:fake
20930     Single-lit-var/imm32/inouts
20931     0/imm32/no-outputs
20932     0/imm32/no-outputs
20933     0x11/imm32/alloc-id:fake
20934     _string_0f_87_jump_label/imm32/subx-name
20935     0/imm32/no-rm32
20936     0/imm32/no-r32
20937     0/imm32/no-imm32
20938     0/imm32/no-imm8
20939     1/imm32/disp32-is-first-inout
20940     0/imm32/no-xm32
20941     0/imm32/no-x32
20942     0x11/imm32/alloc-id:fake
20943     _Primitive-break-if-<-named/imm32/next
20944 _Primitive-break-if-<-named:  # (payload primitive)
20945     0x11/imm32/alloc-id:fake:payload
20946     0x11/imm32/alloc-id:fake
20947     _string-break-if-</imm32/name
20948     0x11/imm32/alloc-id:fake
20949     Single-lit-var/imm32/inouts
20950     0/imm32/no-outputs
20951     0/imm32/no-outputs
20952     0x11/imm32/alloc-id:fake
20953     _string_0f_8c_jump_label/imm32/subx-name
20954     0/imm32/no-rm32
20955     0/imm32/no-r32
20956     0/imm32/no-imm32
20957     0/imm32/no-imm8
20958     1/imm32/disp32-is-first-inout
20959     0/imm32/no-xm32
20960     0/imm32/no-x32
20961     0x11/imm32/alloc-id:fake
20962     _Primitive-break-if->=-named/imm32/next
20963 _Primitive-break-if->=-named:  # (payload primitive)
20964     0x11/imm32/alloc-id:fake:payload
20965     0x11/imm32/alloc-id:fake
20966     _string-break-if->=/imm32/name
20967     0x11/imm32/alloc-id:fake
20968     Single-lit-var/imm32/inouts
20969     0/imm32/no-outputs
20970     0/imm32/no-outputs
20971     0x11/imm32/alloc-id:fake
20972     _string_0f_8d_jump_label/imm32/subx-name
20973     0/imm32/no-rm32
20974     0/imm32/no-r32
20975     0/imm32/no-imm32
20976     0/imm32/no-imm8
20977     1/imm32/disp32-is-first-inout
20978     0/imm32/no-xm32
20979     0/imm32/no-x32
20980     0x11/imm32/alloc-id:fake
20981     _Primitive-break-if-<=-named/imm32/next
20982 _Primitive-break-if-<=-named:  # (payload primitive)
20983     0x11/imm32/alloc-id:fake:payload
20984     0x11/imm32/alloc-id:fake
20985     _string-break-if-<=/imm32/name
20986     0x11/imm32/alloc-id:fake
20987     Single-lit-var/imm32/inouts
20988     0/imm32/no-outputs
20989     0/imm32/no-outputs
20990     0x11/imm32/alloc-id:fake
20991     _string_0f_8e_jump_label/imm32/subx-name
20992     0/imm32/no-rm32
20993     0/imm32/no-r32
20994     0/imm32/no-imm32
20995     0/imm32/no-imm8
20996     1/imm32/disp32-is-first-inout
20997     0/imm32/no-xm32
20998     0/imm32/no-x32
20999     0x11/imm32/alloc-id:fake
21000     _Primitive-break-if->-named/imm32/next
21001 _Primitive-break-if->-named:  # (payload primitive)
21002     0x11/imm32/alloc-id:fake:payload
21003     0x11/imm32/alloc-id:fake
21004     _string-break-if->/imm32/name
21005     0x11/imm32/alloc-id:fake
21006     Single-lit-var/imm32/inouts
21007     0/imm32/no-outputs
21008     0/imm32/no-outputs
21009     0x11/imm32/alloc-id:fake
21010     _string_0f_8f_jump_label/imm32/subx-name
21011     0/imm32/no-rm32
21012     0/imm32/no-r32
21013     0/imm32/no-imm32
21014     0/imm32/no-imm8
21015     1/imm32/disp32-is-first-inout
21016     0/imm32/no-xm32
21017     0/imm32/no-x32
21018     0x11/imm32/alloc-id:fake
21019     _Primitive-break-named/imm32/next
21020 _Primitive-break-named:  # (payload primitive)
21021     0x11/imm32/alloc-id:fake:payload
21022     0x11/imm32/alloc-id:fake
21023     _string-break/imm32/name
21024     0x11/imm32/alloc-id:fake
21025     Single-lit-var/imm32/inouts
21026     0/imm32/no-outputs
21027     0/imm32/no-outputs
21028     0x11/imm32/alloc-id:fake
21029     _string_e9_jump_label/imm32/subx-name
21030     0/imm32/no-rm32
21031     0/imm32/no-r32
21032     0/imm32/no-imm32
21033     0/imm32/no-imm8
21034     1/imm32/disp32-is-first-inout
21035     0/imm32/no-xm32
21036     0/imm32/no-x32
21037     0x11/imm32/alloc-id:fake
21038     _Primitive-loop-if-addr<-named/imm32/next
21039 _Primitive-loop-if-addr<-named:  # (payload primitive)
21040     0x11/imm32/alloc-id:fake:payload
21041     0x11/imm32/alloc-id:fake
21042     _string-loop-if-addr</imm32/name
21043     0x11/imm32/alloc-id:fake
21044     Single-lit-var/imm32/inouts
21045     0/imm32/no-outputs
21046     0/imm32/no-outputs
21047     0x11/imm32/alloc-id:fake
21048     _string_0f_82_jump_label/imm32/subx-name
21049     0/imm32/no-rm32
21050     0/imm32/no-r32
21051     0/imm32/no-imm32
21052     0/imm32/no-imm8
21053     1/imm32/disp32-is-first-inout
21054     0/imm32/no-xm32
21055     0/imm32/no-x32
21056     0x11/imm32/alloc-id:fake
21057     _Primitive-loop-if-addr>=-named/imm32/next
21058 _Primitive-loop-if-addr>=-named:  # (payload primitive)
21059     0x11/imm32/alloc-id:fake:payload
21060     0x11/imm32/alloc-id:fake
21061     _string-loop-if-addr>=/imm32/name
21062     0x11/imm32/alloc-id:fake
21063     Single-lit-var/imm32/inouts
21064     0/imm32/no-outputs
21065     0/imm32/no-outputs
21066     0x11/imm32/alloc-id:fake
21067     _string_0f_83_jump_label/imm32/subx-name
21068     0/imm32/no-rm32
21069     0/imm32/no-r32
21070     0/imm32/no-imm32
21071     0/imm32/no-imm8
21072     1/imm32/disp32-is-first-inout
21073     0/imm32/no-xm32
21074     0/imm32/no-x32
21075     0x11/imm32/alloc-id:fake
21076     _Primitive-loop-if-=-named/imm32/next
21077 _Primitive-loop-if-=-named:  # (payload primitive)
21078     0x11/imm32/alloc-id:fake:payload
21079     0x11/imm32/alloc-id:fake
21080     _string-loop-if-=/imm32/name
21081     0x11/imm32/alloc-id:fake
21082     Single-lit-var/imm32/inouts
21083     0/imm32/no-outputs
21084     0/imm32/no-outputs
21085     0x11/imm32/alloc-id:fake
21086     _string_0f_84_jump_label/imm32/subx-name
21087     0/imm32/no-rm32
21088     0/imm32/no-r32
21089     0/imm32/no-imm32
21090     0/imm32/no-imm8
21091     1/imm32/disp32-is-first-inout
21092     0/imm32/no-xm32
21093     0/imm32/no-x32
21094     0x11/imm32/alloc-id:fake
21095     _Primitive-loop-if-!=-named/imm32/next
21096 _Primitive-loop-if-!=-named:  # (payload primitive)
21097     0x11/imm32/alloc-id:fake:payload
21098     0x11/imm32/alloc-id:fake
21099     _string-loop-if-!=/imm32/name
21100     0x11/imm32/alloc-id:fake
21101     Single-lit-var/imm32/inouts
21102     0/imm32/no-outputs
21103     0/imm32/no-outputs
21104     0x11/imm32/alloc-id:fake
21105     _string_0f_85_jump_label/imm32/subx-name
21106     0/imm32/no-rm32
21107     0/imm32/no-r32
21108     0/imm32/no-imm32
21109     0/imm32/no-imm8
21110     1/imm32/disp32-is-first-inout
21111     0/imm32/no-xm32
21112     0/imm32/no-x32
21113     0x11/imm32/alloc-id:fake
21114     _Primitive-loop-if-addr<=-named/imm32/next
21115 _Primitive-loop-if-addr<=-named:  # (payload primitive)
21116     0x11/imm32/alloc-id:fake:payload
21117     0x11/imm32/alloc-id:fake
21118     _string-loop-if-addr<=/imm32/name
21119     0x11/imm32/alloc-id:fake
21120     Single-lit-var/imm32/inouts
21121     0/imm32/no-outputs
21122     0/imm32/no-outputs
21123     0x11/imm32/alloc-id:fake
21124     _string_0f_86_jump_label/imm32/subx-name
21125     0/imm32/no-rm32
21126     0/imm32/no-r32
21127     0/imm32/no-imm32
21128     0/imm32/no-imm8
21129     1/imm32/disp32-is-first-inout
21130     0/imm32/no-xm32
21131     0/imm32/no-x32
21132     0x11/imm32/alloc-id:fake
21133     _Primitive-loop-if-addr>-named/imm32/next
21134 _Primitive-loop-if-addr>-named:  # (payload primitive)
21135     0x11/imm32/alloc-id:fake:payload
21136     0x11/imm32/alloc-id:fake
21137     _string-loop-if-addr>/imm32/name
21138     0x11/imm32/alloc-id:fake
21139     Single-lit-var/imm32/inouts
21140     0/imm32/no-outputs
21141     0/imm32/no-outputs
21142     0x11/imm32/alloc-id:fake
21143     _string_0f_87_jump_label/imm32/subx-name
21144     0/imm32/no-rm32
21145     0/imm32/no-r32
21146     0/imm32/no-imm32
21147     0/imm32/no-imm8
21148     1/imm32/disp32-is-first-inout
21149     0/imm32/no-xm32
21150     0/imm32/no-x32
21151     0x11/imm32/alloc-id:fake
21152     _Primitive-loop-if-<-named/imm32/next
21153 _Primitive-loop-if-<-named:  # (payload primitive)
21154     0x11/imm32/alloc-id:fake:payload
21155     0x11/imm32/alloc-id:fake
21156     _string-loop-if-</imm32/name
21157     0x11/imm32/alloc-id:fake
21158     Single-lit-var/imm32/inouts
21159     0/imm32/no-outputs
21160     0/imm32/no-outputs
21161     0x11/imm32/alloc-id:fake
21162     _string_0f_8c_jump_label/imm32/subx-name
21163     0/imm32/no-rm32
21164     0/imm32/no-r32
21165     0/imm32/no-imm32
21166     0/imm32/no-imm8
21167     1/imm32/disp32-is-first-inout
21168     0/imm32/no-xm32
21169     0/imm32/no-x32
21170     0x11/imm32/alloc-id:fake
21171     _Primitive-loop-if->=-named/imm32/next
21172 _Primitive-loop-if->=-named:  # (payload primitive)
21173     0x11/imm32/alloc-id:fake:payload
21174     0x11/imm32/alloc-id:fake
21175     _string-loop-if->=/imm32/name
21176     0x11/imm32/alloc-id:fake
21177     Single-lit-var/imm32/inouts
21178     0/imm32/no-outputs
21179     0/imm32/no-outputs
21180     0x11/imm32/alloc-id:fake
21181     _string_0f_8d_jump_label/imm32/subx-name
21182     0/imm32/no-rm32
21183     0/imm32/no-r32
21184     0/imm32/no-imm32
21185     0/imm32/no-imm8
21186     1/imm32/disp32-is-first-inout
21187     0/imm32/no-xm32
21188     0/imm32/no-x32
21189     0x11/imm32/alloc-id:fake
21190     _Primitive-loop-if-<=-named/imm32/next
21191 _Primitive-loop-if-<=-named:  # (payload primitive)
21192     0x11/imm32/alloc-id:fake:payload
21193     0x11/imm32/alloc-id:fake
21194     _string-loop-if-<=/imm32/name
21195     0x11/imm32/alloc-id:fake
21196     Single-lit-var/imm32/inouts
21197     0/imm32/no-outputs
21198     0/imm32/no-outputs
21199     0x11/imm32/alloc-id:fake
21200     _string_0f_8e_jump_label/imm32/subx-name
21201     0/imm32/no-rm32
21202     0/imm32/no-r32
21203     0/imm32/no-imm32
21204     0/imm32/no-imm8
21205     1/imm32/disp32-is-first-inout
21206     0/imm32/no-xm32
21207     0/imm32/no-x32
21208     0x11/imm32/alloc-id:fake
21209     _Primitive-loop-if->-named/imm32/next
21210 _Primitive-loop-if->-named:  # (payload primitive)
21211     0x11/imm32/alloc-id:fake:payload
21212     0x11/imm32/alloc-id:fake
21213     _string-loop-if->/imm32/name
21214     0x11/imm32/alloc-id:fake
21215     Single-lit-var/imm32/inouts
21216     0/imm32/no-outputs
21217     0/imm32/no-outputs
21218     0x11/imm32/alloc-id:fake
21219     _string_0f_8f_jump_label/imm32/subx-name
21220     0/imm32/no-rm32
21221     0/imm32/no-r32
21222     0/imm32/no-imm32
21223     0/imm32/no-imm8
21224     1/imm32/disp32-is-first-inout
21225     0/imm32/no-xm32
21226     0/imm32/no-x32
21227     0x11/imm32/alloc-id:fake
21228     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
21229 _Primitive-loop-named:  # (payload primitive)
21230     0x11/imm32/alloc-id:fake:payload
21231     0x11/imm32/alloc-id:fake
21232     _string-loop/imm32/name
21233     0x11/imm32/alloc-id:fake
21234     Single-lit-var/imm32/inouts
21235     0/imm32/no-outputs
21236     0/imm32/no-outputs
21237     0x11/imm32/alloc-id:fake
21238     _string_e9_jump_label/imm32/subx-name
21239     0/imm32/no-rm32
21240     0/imm32/no-r32
21241     0/imm32/no-imm32
21242     0/imm32/no-imm8
21243     1/imm32/disp32-is-first-inout
21244     0/imm32/no-xm32
21245     0/imm32/no-x32
21246     0x11/imm32/alloc-id:fake
21247     _Primitive-break-if-float</imm32/next
21248 # - branches based on floating-point comparisons
21249 _Primitive-break-if-float<:  # (payload primitive)
21250     0x11/imm32/alloc-id:fake:payload
21251     0x11/imm32/alloc-id:fake
21252     _string-break-if-float</imm32/name
21253     0/imm32/no-inouts
21254     0/imm32/no-inouts
21255     0/imm32/no-outputs
21256     0/imm32/no-outputs
21257     0x11/imm32/alloc-id:fake
21258     _string_0f_82_jump_break/imm32/subx-name
21259     0/imm32/no-rm32
21260     0/imm32/no-r32
21261     0/imm32/no-imm32
21262     0/imm32/no-imm8
21263     0/imm32/no-disp32
21264     0/imm32/no-xm32
21265     0/imm32/no-x32
21266     0x11/imm32/alloc-id:fake
21267     _Primitive-break-if-float>=/imm32/next
21268 _Primitive-break-if-float>=:  # (payload primitive)
21269     0x11/imm32/alloc-id:fake:payload
21270     0x11/imm32/alloc-id:fake
21271     _string-break-if-float>=/imm32/name
21272     0/imm32/no-inouts
21273     0/imm32/no-inouts
21274     0/imm32/no-outputs
21275     0/imm32/no-outputs
21276     0x11/imm32/alloc-id:fake
21277     _string_0f_83_jump_break/imm32/subx-name
21278     0/imm32/no-rm32
21279     0/imm32/no-r32
21280     0/imm32/no-imm32
21281     0/imm32/no-imm8
21282     0/imm32/no-disp32
21283     0/imm32/no-xm32
21284     0/imm32/no-x32
21285     0x11/imm32/alloc-id:fake
21286     _Primitive-break-if-float<=/imm32/next
21287 _Primitive-break-if-float<=:  # (payload primitive)
21288     0x11/imm32/alloc-id:fake:payload
21289     0x11/imm32/alloc-id:fake
21290     _string-break-if-float<=/imm32/name
21291     0/imm32/no-inouts
21292     0/imm32/no-inouts
21293     0/imm32/no-outputs
21294     0/imm32/no-outputs
21295     0x11/imm32/alloc-id:fake
21296     _string_0f_86_jump_break/imm32/subx-name
21297     0/imm32/no-rm32
21298     0/imm32/no-r32
21299     0/imm32/no-imm32
21300     0/imm32/no-imm8
21301     0/imm32/no-disp32
21302     0/imm32/no-xm32
21303     0/imm32/no-x32
21304     0x11/imm32/alloc-id:fake
21305     _Primitive-break-if-float>/imm32/next
21306 _Primitive-break-if-float>:  # (payload primitive)
21307     0x11/imm32/alloc-id:fake:payload
21308     0x11/imm32/alloc-id:fake
21309     _string-break-if-float>/imm32/name
21310     0/imm32/no-inouts
21311     0/imm32/no-inouts
21312     0/imm32/no-outputs
21313     0/imm32/no-outputs
21314     0x11/imm32/alloc-id:fake
21315     _string_0f_87_jump_break/imm32/subx-name
21316     0/imm32/no-rm32
21317     0/imm32/no-r32
21318     0/imm32/no-imm32
21319     0/imm32/no-imm8
21320     0/imm32/no-disp32
21321     0/imm32/no-xm32
21322     0/imm32/no-x32
21323     0x11/imm32/alloc-id:fake
21324     _Primitive-loop-if-float</imm32/next
21325 _Primitive-loop-if-float<:  # (payload primitive)
21326     0x11/imm32/alloc-id:fake:payload
21327     0x11/imm32/alloc-id:fake
21328     _string-loop-if-float</imm32/name
21329     0/imm32/no-inouts
21330     0/imm32/no-inouts
21331     0/imm32/no-outputs
21332     0/imm32/no-outputs
21333     0x11/imm32/alloc-id:fake
21334     _string_0f_82_jump_loop/imm32/subx-name
21335     0/imm32/no-rm32
21336     0/imm32/no-r32
21337     0/imm32/no-imm32
21338     0/imm32/no-imm8
21339     0/imm32/no-disp32
21340     0/imm32/no-xm32
21341     0/imm32/no-x32
21342     0x11/imm32/alloc-id:fake
21343     _Primitive-loop-if-float>=/imm32/next
21344 _Primitive-loop-if-float>=:  # (payload primitive)
21345     0x11/imm32/alloc-id:fake:payload
21346     0x11/imm32/alloc-id:fake
21347     _string-loop-if-float>=/imm32/name
21348     0/imm32/no-inouts
21349     0/imm32/no-inouts
21350     0/imm32/no-outputs
21351     0/imm32/no-outputs
21352     0x11/imm32/alloc-id:fake
21353     _string_0f_83_jump_loop/imm32/subx-name
21354     0/imm32/no-rm32
21355     0/imm32/no-r32
21356     0/imm32/no-imm32
21357     0/imm32/no-imm8
21358     0/imm32/no-disp32
21359     0/imm32/no-xm32
21360     0/imm32/no-x32
21361     0x11/imm32/alloc-id:fake
21362     _Primitive-loop-if-float<=/imm32/next
21363 _Primitive-loop-if-float<=:  # (payload primitive)
21364     0x11/imm32/alloc-id:fake:payload
21365     0x11/imm32/alloc-id:fake
21366     _string-loop-if-float<=/imm32/name
21367     0/imm32/no-inouts
21368     0/imm32/no-inouts
21369     0/imm32/no-outputs
21370     0/imm32/no-outputs
21371     0x11/imm32/alloc-id:fake
21372     _string_0f_86_jump_loop/imm32/subx-name
21373     0/imm32/no-rm32
21374     0/imm32/no-r32
21375     0/imm32/no-imm32
21376     0/imm32/no-imm8
21377     0/imm32/no-disp32
21378     0/imm32/no-xm32
21379     0/imm32/no-x32
21380     0x11/imm32/alloc-id:fake
21381     _Primitive-loop-if-float>/imm32/next
21382 _Primitive-loop-if-float>:  # (payload primitive)
21383     0x11/imm32/alloc-id:fake:payload
21384     0x11/imm32/alloc-id:fake
21385     _string-loop-if-float>/imm32/name
21386     0/imm32/no-inouts
21387     0/imm32/no-inouts
21388     0/imm32/no-outputs
21389     0/imm32/no-outputs
21390     0x11/imm32/alloc-id:fake
21391     _string_0f_87_jump_loop/imm32/subx-name
21392     0/imm32/no-rm32
21393     0/imm32/no-r32
21394     0/imm32/no-imm32
21395     0/imm32/no-imm8
21396     0/imm32/no-disp32
21397     0/imm32/no-xm32
21398     0/imm32/no-x32
21399     0x11/imm32/alloc-id:fake
21400     _Primitive-break-if-float<-named/imm32/next
21401 _Primitive-break-if-float<-named:  # (payload primitive)
21402     0x11/imm32/alloc-id:fake:payload
21403     0x11/imm32/alloc-id:fake
21404     _string-break-if-float</imm32/name
21405     0x11/imm32/alloc-id:fake
21406     Single-lit-var/imm32/inouts
21407     0/imm32/no-outputs
21408     0/imm32/no-outputs
21409     0x11/imm32/alloc-id:fake
21410     _string_0f_82_jump_label/imm32/subx-name
21411     0/imm32/no-rm32
21412     0/imm32/no-r32
21413     0/imm32/no-imm32
21414     0/imm32/no-imm8
21415     1/imm32/disp32-is-first-inout
21416     0/imm32/no-xm32
21417     0/imm32/no-x32
21418     0x11/imm32/alloc-id:fake
21419     _Primitive-break-if-float>=-named/imm32/next
21420 _Primitive-break-if-float>=-named:  # (payload primitive)
21421     0x11/imm32/alloc-id:fake:payload
21422     0x11/imm32/alloc-id:fake
21423     _string-break-if-float>=/imm32/name
21424     0x11/imm32/alloc-id:fake
21425     Single-lit-var/imm32/inouts
21426     0/imm32/no-outputs
21427     0/imm32/no-outputs
21428     0x11/imm32/alloc-id:fake
21429     _string_0f_83_jump_label/imm32/subx-name
21430     0/imm32/no-rm32
21431     0/imm32/no-r32
21432     0/imm32/no-imm32
21433     0/imm32/no-imm8
21434     1/imm32/disp32-is-first-inout
21435     0/imm32/no-xm32
21436     0/imm32/no-x32
21437     0x11/imm32/alloc-id:fake
21438     _Primitive-break-if-float<=-named/imm32/next
21439 _Primitive-break-if-float<=-named:  # (payload primitive)
21440     0x11/imm32/alloc-id:fake:payload
21441     0x11/imm32/alloc-id:fake
21442     _string-break-if-float<=/imm32/name
21443     0x11/imm32/alloc-id:fake
21444     Single-lit-var/imm32/inouts
21445     0/imm32/no-outputs
21446     0/imm32/no-outputs
21447     0x11/imm32/alloc-id:fake
21448     _string_0f_86_jump_label/imm32/subx-name
21449     0/imm32/no-rm32
21450     0/imm32/no-r32
21451     0/imm32/no-imm32
21452     0/imm32/no-imm8
21453     1/imm32/disp32-is-first-inout
21454     0/imm32/no-xm32
21455     0/imm32/no-x32
21456     0x11/imm32/alloc-id:fake
21457     _Primitive-break-if-float>-named/imm32/next
21458 _Primitive-break-if-float>-named:  # (payload primitive)
21459     0x11/imm32/alloc-id:fake:payload
21460     0x11/imm32/alloc-id:fake
21461     _string-break-if-float>/imm32/name
21462     0x11/imm32/alloc-id:fake
21463     Single-lit-var/imm32/inouts
21464     0/imm32/no-outputs
21465     0/imm32/no-outputs
21466     0x11/imm32/alloc-id:fake
21467     _string_0f_87_jump_label/imm32/subx-name
21468     0/imm32/no-rm32
21469     0/imm32/no-r32
21470     0/imm32/no-imm32
21471     0/imm32/no-imm8
21472     1/imm32/disp32-is-first-inout
21473     0/imm32/no-xm32
21474     0/imm32/no-x32
21475     0x11/imm32/alloc-id:fake
21476     _Primitive-loop-if-float<-named/imm32/next
21477 _Primitive-loop-if-float<-named:  # (payload primitive)
21478     0x11/imm32/alloc-id:fake:payload
21479     0x11/imm32/alloc-id:fake
21480     _string-loop-if-float</imm32/name
21481     0x11/imm32/alloc-id:fake
21482     Single-lit-var/imm32/inouts
21483     0/imm32/no-outputs
21484     0/imm32/no-outputs
21485     0x11/imm32/alloc-id:fake
21486     _string_0f_82_jump_label/imm32/subx-name
21487     0/imm32/no-rm32
21488     0/imm32/no-r32
21489     0/imm32/no-imm32
21490     0/imm32/no-imm8
21491     1/imm32/disp32-is-first-inout
21492     0/imm32/no-xm32
21493     0/imm32/no-x32
21494     0x11/imm32/alloc-id:fake
21495     _Primitive-loop-if-float>=-named/imm32/next
21496 _Primitive-loop-if-float>=-named:  # (payload primitive)
21497     0x11/imm32/alloc-id:fake:payload
21498     0x11/imm32/alloc-id:fake
21499     _string-loop-if-float>=/imm32/name
21500     0x11/imm32/alloc-id:fake
21501     Single-lit-var/imm32/inouts
21502     0/imm32/no-outputs
21503     0/imm32/no-outputs
21504     0x11/imm32/alloc-id:fake
21505     _string_0f_83_jump_label/imm32/subx-name
21506     0/imm32/no-rm32
21507     0/imm32/no-r32
21508     0/imm32/no-imm32
21509     0/imm32/no-imm8
21510     1/imm32/disp32-is-first-inout
21511     0/imm32/no-xm32
21512     0/imm32/no-x32
21513     0x11/imm32/alloc-id:fake
21514     _Primitive-loop-if-float<=-named/imm32/next
21515 _Primitive-loop-if-float<=-named:  # (payload primitive)
21516     0x11/imm32/alloc-id:fake:payload
21517     0x11/imm32/alloc-id:fake
21518     _string-loop-if-float<=/imm32/name
21519     0x11/imm32/alloc-id:fake
21520     Single-lit-var/imm32/inouts
21521     0/imm32/no-outputs
21522     0/imm32/no-outputs
21523     0x11/imm32/alloc-id:fake
21524     _string_0f_86_jump_label/imm32/subx-name
21525     0/imm32/no-rm32
21526     0/imm32/no-r32
21527     0/imm32/no-imm32
21528     0/imm32/no-imm8
21529     1/imm32/disp32-is-first-inout
21530     0/imm32/no-xm32
21531     0/imm32/no-x32
21532     0x11/imm32/alloc-id:fake
21533     _Primitive-loop-if-float>-named/imm32/next
21534 _Primitive-loop-if-float>-named:  # (payload primitive)
21535     0x11/imm32/alloc-id:fake:payload
21536     0x11/imm32/alloc-id:fake
21537     _string-loop-if-float>/imm32/name
21538     0x11/imm32/alloc-id:fake
21539     Single-lit-var/imm32/inouts
21540     0/imm32/no-outputs
21541     0/imm32/no-outputs
21542     0x11/imm32/alloc-id:fake
21543     _string_0f_87_jump_label/imm32/subx-name
21544     0/imm32/no-rm32
21545     0/imm32/no-r32
21546     0/imm32/no-imm32
21547     0/imm32/no-imm8
21548     1/imm32/disp32-is-first-inout
21549     0/imm32/no-xm32
21550     0/imm32/no-x32
21551     0/imm32/next
21552     0/imm32/next
21553 
21554 # string literals for Mu instructions
21555 _string-add:  # (payload array byte)
21556     0x11/imm32/alloc-id:fake:payload
21557     # "add"
21558     0x3/imm32/size
21559     0x61/a 0x64/d 0x64/d
21560 _string-address:  # (payload array byte)
21561     0x11/imm32/alloc-id:fake:payload
21562     # "address"
21563     0x7/imm32/size
21564     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
21565 _string-add-to:  # (payload array byte)
21566     0x11/imm32/alloc-id:fake:payload
21567     # "add-to"
21568     0x6/imm32/size
21569     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
21570 _string-and:  # (payload array byte)
21571     0x11/imm32/alloc-id:fake:payload
21572     # "and"
21573     0x3/imm32/size
21574     0x61/a 0x6e/n 0x64/d
21575 _string-and-with:  # (payload array byte)
21576     0x11/imm32/alloc-id:fake:payload
21577     # "and-with"
21578     0x8/imm32/size
21579     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
21580 _string-break:  # (payload array byte)
21581     0x11/imm32/alloc-id:fake:payload
21582     # "break"
21583     0x5/imm32/size
21584     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
21585 _string-break-if-<:  # (payload array byte)
21586     0x11/imm32/alloc-id:fake:payload
21587     # "break-if-<"
21588     0xa/imm32/size
21589     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
21590 _string-break-if-<=:  # (payload array byte)
21591     0x11/imm32/alloc-id:fake:payload
21592     # "break-if-<="
21593     0xb/imm32/size
21594     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
21595 _string-break-if-=:  # (payload array byte)
21596     0x11/imm32/alloc-id:fake:payload
21597     # "break-if-="
21598     0xa/imm32/size
21599     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
21600 _string-break-if->:  # (payload array byte)
21601     0x11/imm32/alloc-id:fake:payload
21602     # "break-if->"
21603     0xa/imm32/size
21604     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
21605 _string-break-if->=:  # (payload array byte)
21606     0x11/imm32/alloc-id:fake:payload
21607     # "break-if->="
21608     0xb/imm32/size
21609     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
21610 _string-break-if-!=:  # (payload array byte)
21611     0x11/imm32/alloc-id:fake:payload
21612     # "break-if-!="
21613     0xb/imm32/size
21614     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
21615 _string-break-if-addr<:  # (payload array byte)
21616     0x11/imm32/alloc-id:fake:payload
21617     # "break-if-addr<"
21618     0xe/imm32/size
21619     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/<
21620 _string-break-if-addr<=:  # (payload array byte)
21621     0x11/imm32/alloc-id:fake:payload
21622     # "break-if-addr<="
21623     0xf/imm32/size
21624     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/=
21625 _string-break-if-addr>:  # (payload array byte)
21626     0x11/imm32/alloc-id:fake:payload
21627     # "break-if-addr>"
21628     0xe/imm32/size
21629     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/>
21630 _string-break-if-addr>=:  # (payload array byte)
21631     0x11/imm32/alloc-id:fake:payload
21632     # "break-if-addr>="
21633     0xf/imm32/size
21634     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/=
21635 _string-break-if-float<:  # (payload array byte)
21636     0x11/imm32/alloc-id:fake:payload
21637     # "break-if-float<"
21638     0xf/imm32/size
21639     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/<
21640 _string-break-if-float<=:  # (payload array byte)
21641     0x11/imm32/alloc-id:fake:payload
21642     # "break-if-float<="
21643     0x10/imm32/size
21644     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/=
21645 _string-break-if-float>:  # (payload array byte)
21646     0x11/imm32/alloc-id:fake:payload
21647     # "break-if-float>"
21648     0xf/imm32/size
21649     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/>
21650 _string-break-if-float>=:  # (payload array byte)
21651     0x11/imm32/alloc-id:fake:payload
21652     # "break-if-float>="
21653     0x10/imm32/size
21654     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/=
21655 _string-compare:  # (payload array byte)
21656     0x11/imm32/alloc-id:fake:payload
21657     # "compare"
21658     0x7/imm32/size
21659     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
21660 _string-copy:  # (payload array byte)
21661     0x11/imm32/alloc-id:fake:payload
21662     # "copy"
21663     0x4/imm32/size
21664     0x63/c 0x6f/o 0x70/p 0x79/y
21665 _string-copy-to:  # (payload array byte)
21666     0x11/imm32/alloc-id:fake:payload
21667     # "copy-to"
21668     0x7/imm32/size
21669     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
21670 _string-copy-byte:
21671     0x11/imm32/alloc-id:fake:payload
21672     # "copy-byte"
21673     0x9/imm32/size
21674     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
21675 _string-copy-byte-to:
21676     0x11/imm32/alloc-id:fake:payload
21677     # "copy-byte-to"
21678     0xc/imm32/size
21679     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
21680 _string-decrement:  # (payload array byte)
21681     0x11/imm32/alloc-id:fake:payload
21682     # "decrement"
21683     0x9/imm32/size
21684     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
21685 _string-increment:  # (payload array byte)
21686     0x11/imm32/alloc-id:fake:payload
21687     # "increment"
21688     0x9/imm32/size
21689     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
21690 _string-loop:  # (payload array byte)
21691     0x11/imm32/alloc-id:fake:payload
21692     # "loop"
21693     0x4/imm32/size
21694     0x6c/l 0x6f/o 0x6f/o 0x70/p
21695 _string-loop-if-<:  # (payload array byte)
21696     0x11/imm32/alloc-id:fake:payload
21697     # "loop-if-<"
21698     0x9/imm32/size
21699     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
21700 _string-loop-if-<=:  # (payload array byte)
21701     0x11/imm32/alloc-id:fake:payload
21702     # "loop-if-<="
21703     0xa/imm32/size
21704     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
21705 _string-loop-if-=:  # (payload array byte)
21706     0x11/imm32/alloc-id:fake:payload
21707     # "loop-if-="
21708     0x9/imm32/size
21709     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
21710 _string-loop-if->:  # (payload array byte)
21711     0x11/imm32/alloc-id:fake:payload
21712     # "loop-if->"
21713     0x9/imm32/size
21714     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
21715 _string-loop-if->=:  # (payload array byte)
21716     0x11/imm32/alloc-id:fake:payload
21717     # "loop-if->="
21718     0xa/imm32/size
21719     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
21720 _string-loop-if-!=:  # (payload array byte)
21721     0x11/imm32/alloc-id:fake:payload
21722     # "loop-if-!="
21723     0xa/imm32/size
21724     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
21725 _string-loop-if-addr<:  # (payload array byte)
21726     0x11/imm32/alloc-id:fake:payload
21727     # "loop-if-addr<"
21728     0xd/imm32/size
21729     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/<
21730 _string-loop-if-addr<=:  # (payload array byte)
21731     0x11/imm32/alloc-id:fake:payload
21732     # "loop-if-addr<="
21733     0xe/imm32/size
21734     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/=
21735 _string-loop-if-addr>:  # (payload array byte)
21736     0x11/imm32/alloc-id:fake:payload
21737     # "loop-if-addr>"
21738     0xd/imm32/size
21739     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/>
21740 _string-loop-if-addr>=:  # (payload array byte)
21741     0x11/imm32/alloc-id:fake:payload
21742     # "loop-if-addr>="
21743     0xe/imm32/size
21744     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/=
21745 _string-loop-if-float<:  # (payload array byte)
21746     0x11/imm32/alloc-id:fake:payload
21747     # "loop-if-float<"
21748     0xe/imm32/size
21749     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/<
21750 _string-loop-if-float<=:  # (payload array byte)
21751     0x11/imm32/alloc-id:fake:payload
21752     # "loop-if-float<="
21753     0xf/imm32/size
21754     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/=
21755 _string-loop-if-float>:  # (payload array byte)
21756     0x11/imm32/alloc-id:fake:payload
21757     # "loop-if-float>"
21758     0xe/imm32/size
21759     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/>
21760 _string-loop-if-float>=:  # (payload array byte)
21761     0x11/imm32/alloc-id:fake:payload
21762     # "loop-if-float>="
21763     0xf/imm32/size
21764     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/=
21765 _string-multiply:  # (payload array byte)
21766     0x11/imm32/alloc-id:fake:payload
21767     # "multiply"
21768     0x8/imm32/size
21769     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
21770 _string-convert:  # (payload array byte)
21771     0x11/imm32/alloc-id:fake:payload
21772     # "convert"
21773     0x7/imm32/size
21774     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
21775 _string-truncate:  # (payload array byte)
21776     0x11/imm32/alloc-id:fake:payload
21777     # "truncate"
21778     0x8/imm32/size
21779     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
21780 _string-reinterpret:  # (payload array byte)
21781     0x11/imm32/alloc-id:fake:payload
21782     # "reinterpret"
21783     0xb/imm32/size
21784     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
21785 _string-divide:
21786     0x11/imm32/alloc-id:fake:payload
21787     # "divide"
21788     0x6/imm32/size
21789     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
21790 _string-max:
21791     0x11/imm32/alloc-id:fake:payload
21792     # "max"
21793     0x3/imm32/size
21794     0x6d/m 0x61/a 0x78/x
21795 _string-min:
21796     0x11/imm32/alloc-id:fake:payload
21797     # "min"
21798     0x3/imm32/size
21799     0x6d/m 0x69/i 0x6e/n
21800 _string-reciprocal:
21801     0x11/imm32/alloc-id:fake:payload
21802     # "reciprocal"
21803     0xa/imm32/size
21804     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
21805 _string-square-root:
21806     0x11/imm32/alloc-id:fake:payload
21807     # "square-root"
21808     0xb/imm32/size
21809     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
21810 _string-inverse-square-root:
21811     0x11/imm32/alloc-id:fake:payload
21812     # "inverse-square-root"
21813     0x13/imm32/size
21814     0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
21815 _string-negate:  # (payload array byte)
21816     0x11/imm32/alloc-id:fake:payload
21817     # "negate"
21818     0x6/imm32/size
21819     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
21820 _string-or:  # (payload array byte)
21821     0x11/imm32/alloc-id:fake:payload
21822     # "or"
21823     0x2/imm32/size
21824     0x6f/o 0x72/r
21825 _string-or-with:  # (payload array byte)
21826     0x11/imm32/alloc-id:fake:payload
21827     # "or-with"
21828     0x7/imm32/size
21829     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
21830 _string-subtract:  # (payload array byte)
21831     0x11/imm32/alloc-id:fake:payload
21832     # "subtract"
21833     0x8/imm32/size
21834     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
21835 _string-subtract-from:  # (payload array byte)
21836     0x11/imm32/alloc-id:fake:payload
21837     # "subtract-from"
21838     0xd/imm32/size
21839     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
21840 _string-xor:  # (payload array byte)
21841     0x11/imm32/alloc-id:fake:payload
21842     # "xor"
21843     0x3/imm32/size
21844     0x78/x 0x6f/o 0x72/r
21845 _string-xor-with:  # (payload array byte)
21846     0x11/imm32/alloc-id:fake:payload
21847     # "xor-with"
21848     0x8/imm32/size
21849     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
21850 _string-shift-left:  # (payload array byte)
21851     0x11/imm32/alloc-id:fake:payload
21852     # "shift-left"
21853     0xa/imm32/size
21854     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
21855 _string-shift-right:  # (payload array byte)
21856     0x11/imm32/alloc-id:fake:payload
21857     # "shift-right"
21858     0xb/imm32/size
21859     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
21860 _string-shift-right-signed:  # (payload array byte)
21861     0x11/imm32/alloc-id:fake:payload
21862     # "shift-right-signed"
21863     0x12/imm32/size
21864     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
21865 
21866 # string literals for SubX instructions
21867 _string_01_add_to:  # (payload array byte)
21868     0x11/imm32/alloc-id:fake:payload
21869     # "01/add-to"
21870     0x9/imm32/size
21871     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
21872 _string_03_add:  # (payload array byte)
21873     0x11/imm32/alloc-id:fake:payload
21874     # "03/add"
21875     0x6/imm32/size
21876     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
21877 _string_05_add_to_eax:  # (payload array byte)
21878     0x11/imm32/alloc-id:fake:payload
21879     # "05/add-to-eax"
21880     0xd/imm32/size
21881     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
21882 _string_09_or_with:  # (payload array byte)
21883     0x11/imm32/alloc-id:fake:payload
21884     # "09/or-with"
21885     0xa/imm32/size
21886     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
21887 _string_0b_or:  # (payload array byte)
21888     0x11/imm32/alloc-id:fake:payload
21889     # "0b/or"
21890     0x5/imm32/size
21891     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
21892 _string_0d_or_with_eax:  # (payload array byte)
21893     0x11/imm32/alloc-id:fake:payload
21894     # "0d/or-with-eax"
21895     0xe/imm32/size
21896     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
21897 _string_0f_82_jump_label:  # (payload array byte)
21898     0x11/imm32/alloc-id:fake:payload
21899     # "0f 82/jump-if-addr<"
21900     0x13/imm32/size
21901     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/<
21902 _string_0f_82_jump_break:  # (payload array byte)
21903     0x11/imm32/alloc-id:fake:payload
21904     # "0f 82/jump-if-addr< break/disp32"
21905     0x20/imm32/size
21906     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
21907 _string_0f_82_jump_loop:  # (payload array byte)
21908     0x11/imm32/alloc-id:fake:payload
21909     # "0f 82/jump-if-addr< loop/disp32"
21910     0x1f/imm32/size
21911     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
21912 _string_0f_83_jump_label:  # (payload array byte)
21913     0x11/imm32/alloc-id:fake:payload
21914     # "0f 83/jump-if-addr>="
21915     0x14/imm32/size
21916     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/=
21917 _string_0f_83_jump_break:  # (payload array byte)
21918     0x11/imm32/alloc-id:fake:payload
21919     # "0f 83/jump-if-addr>= break/disp32"
21920     0x21/imm32/size
21921     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
21922 _string_0f_83_jump_loop:  # (payload array byte)
21923     0x11/imm32/alloc-id:fake:payload
21924     # "0f 83/jump-if-addr>= loop/disp32"
21925     0x20/imm32/size
21926     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
21927 _string_0f_84_jump_label:  # (payload array byte)
21928     0x11/imm32/alloc-id:fake:payload
21929     # "0f 84/jump-if-="
21930     0xf/imm32/size
21931     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/=
21932 _string_0f_84_jump_break:  # (payload array byte)
21933     0x11/imm32/alloc-id:fake:payload
21934     # "0f 84/jump-if-= break/disp32"
21935     0x1c/imm32/size
21936     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
21937 _string_0f_84_jump_loop:  # (payload array byte)
21938     0x11/imm32/alloc-id:fake:payload
21939     # "0f 84/jump-if-= loop/disp32"
21940     0x1b/imm32/size
21941     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
21942 _string_0f_85_jump_label:  # (payload array byte)
21943     0x11/imm32/alloc-id:fake:payload
21944     # "0f 85/jump-if-!="
21945     0x10/imm32/size
21946     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/=
21947 _string_0f_85_jump_break:  # (payload array byte)
21948     0x11/imm32/alloc-id:fake:payload
21949     # "0f 85/jump-if-!= break/disp32"
21950     0x1d/imm32/size
21951     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
21952 _string_0f_85_jump_loop:  # (payload array byte)
21953     0x11/imm32/alloc-id:fake:payload
21954     # "0f 85/jump-if-!= loop/disp32"
21955     0x1c/imm32/size
21956     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
21957 _string_0f_86_jump_label:  # (payload array byte)
21958     0x11/imm32/alloc-id:fake:payload
21959     # "0f 86/jump-if-addr<="
21960     0x14/imm32/size
21961     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/=
21962 _string_0f_86_jump_break:  # (payload array byte)
21963     0x11/imm32/alloc-id:fake:payload
21964     # "0f 86/jump-if-addr<= break/disp32"
21965     0x21/imm32/size
21966     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
21967 _string_0f_86_jump_loop:  # (payload array byte)
21968     0x11/imm32/alloc-id:fake:payload
21969     # "0f 86/jump-if-addr<= loop/disp32"
21970     0x20/imm32/size
21971     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
21972 _string_0f_87_jump_label:  # (payload array byte)
21973     0x11/imm32/alloc-id:fake:payload
21974     # "0f 87/jump-if-addr>"
21975     0x13/imm32/size
21976     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/>
21977 _string_0f_87_jump_break:  # (payload array byte)
21978     0x11/imm32/alloc-id:fake:payload
21979     # "0f 87/jump-if-addr> break/disp32"
21980     0x20/imm32/size
21981     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
21982 _string_0f_87_jump_loop:  # (payload array byte)
21983     0x11/imm32/alloc-id:fake:payload
21984     # "0f 87/jump-if-addr> loop/disp32"
21985     0x1f/imm32/size
21986     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
21987 _string_0f_8c_jump_label:  # (payload array byte)
21988     0x11/imm32/alloc-id:fake:payload
21989     # "0f 8c/jump-if-<"
21990     0xf/imm32/size
21991     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/<
21992 _string_0f_8c_jump_break:  # (payload array byte)
21993     0x11/imm32/alloc-id:fake:payload
21994     # "0f 8c/jump-if-< break/disp32"
21995     0x1c/imm32/size
21996     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
21997 _string_0f_8c_jump_loop:  # (payload array byte)
21998     0x11/imm32/alloc-id:fake:payload
21999     # "0f 8c/jump-if-< loop/disp32"
22000     0x1b/imm32/size
22001     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
22002 _string_0f_8d_jump_label:  # (payload array byte)
22003     0x11/imm32/alloc-id:fake:payload
22004     # "0f 8d/jump-if->="
22005     0x10/imm32/size
22006     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/=
22007 _string_0f_8d_jump_break:  # (payload array byte)
22008     0x11/imm32/alloc-id:fake:payload
22009     # "0f 8d/jump-if->= break/disp32"
22010     0x1d/imm32/size
22011     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
22012 _string_0f_8d_jump_loop:  # (payload array byte)
22013     0x11/imm32/alloc-id:fake:payload
22014     # "0f 8d/jump-if->= loop/disp32"
22015     0x1c/imm32/size
22016     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
22017 _string_0f_8e_jump_label:  # (payload array byte)
22018     0x11/imm32/alloc-id:fake:payload
22019     # "0f 8e/jump-if-<="
22020     0x10/imm32/size
22021     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/=
22022 _string_0f_8e_jump_break:  # (payload array byte)
22023     0x11/imm32/alloc-id:fake:payload
22024     # "0f 8e/jump-if-<= break/disp32"
22025     0x1d/imm32/size
22026     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
22027 _string_0f_8e_jump_loop:  # (payload array byte)
22028     0x11/imm32/alloc-id:fake:payload
22029     # "0f 8e/jump-if-<= loop/disp32"
22030     0x1c/imm32/size
22031     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
22032 _string_0f_8f_jump_label:  # (payload array byte)
22033     0x11/imm32/alloc-id:fake:payload
22034     # "0f 8f/jump-if->"
22035     0xf/imm32/size
22036     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/>
22037 _string_0f_8f_jump_break:  # (payload array byte)
22038     0x11/imm32/alloc-id:fake:payload
22039     # "0f 8f/jump-if-> break/disp32"
22040     0x1c/imm32/size
22041     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
22042 _string_0f_8f_jump_loop:  # (payload array byte)
22043     0x11/imm32/alloc-id:fake:payload
22044     # "0f 8f/jump-if-> loop/disp32"
22045     0x1b/imm32/size
22046     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
22047 _string_0f_af_multiply:  # (payload array byte)
22048     0x11/imm32/alloc-id:fake:payload
22049     # "0f af/multiply"
22050     0xe/imm32/size
22051     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
22052 _string_f3_0f_2a_convert_to_float:
22053     0x11/imm32/alloc-id:fake:payload
22054     # "f3 0f 2a/convert-to-float"
22055     0x19/imm32/size
22056     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
22057 _string_f3_0f_2d_convert_to_int:
22058     0x11/imm32/alloc-id:fake:payload
22059     # "f3 0f 2d/convert-to-int"
22060     0x17/imm32/size
22061     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
22062 _string_f3_0f_2c_truncate_to_int:
22063     0x11/imm32/alloc-id:fake:payload
22064     # "f3 0f 2c/truncate-to-int"
22065     0x18/imm32/size
22066     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
22067 _string_f3_0f_58_add:
22068     0x11/imm32/alloc-id:fake:payload
22069     # "f3 0f 58/add"
22070     0xc/imm32/size
22071     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
22072 _string_f3_0f_5c_subtract:
22073     0x11/imm32/alloc-id:fake:payload
22074     # "f3 0f 5c/subtract"
22075     0x11/imm32/size
22076     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
22077 _string_f3_0f_59_multiply:
22078     0x11/imm32/alloc-id:fake:payload
22079     # "f3 0f 59/multiply"
22080     0x11/imm32/size
22081     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
22082 _string_f3_0f_5e_divide:
22083     0x11/imm32/alloc-id:fake:payload
22084     # "f3 0f 5e/divide"
22085     0xf/imm32/size
22086     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
22087 _string_f3_0f_53_reciprocal:
22088     0x11/imm32/alloc-id:fake:payload
22089     # "f3 0f 53/reciprocal"
22090     0x13/imm32/size
22091     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
22092 _string_f3_0f_51_square_root:
22093     0x11/imm32/alloc-id:fake:payload
22094     # "f3 0f 51/square-root"
22095     0x14/imm32/size
22096     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
22097 _string_f3_0f_52_inverse_square_root:
22098     0x11/imm32/alloc-id:fake:payload
22099     # "f3 0f 52/inverse-square-root"
22100     0x1c/imm32/size
22101     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
22102 _string_f3_0f_5d_min:
22103     0x11/imm32/alloc-id:fake:payload
22104     # "f3 0f 5d/min"
22105     0xc/imm32/size
22106     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
22107 _string_f3_0f_5f_max:
22108     0x11/imm32/alloc-id:fake:payload
22109     # "f3 0f 5f/max"
22110     0xc/imm32/size
22111     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
22112 _string_f3_0f_10_copy:
22113     0x11/imm32/alloc-id:fake:payload
22114     # "f3 0f 10/copy"
22115     0xd/imm32/size
22116     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
22117 _string_f3_0f_11_copy:
22118     0x11/imm32/alloc-id:fake:payload
22119     # "f3 0f 11/copy"
22120     0xd/imm32/size
22121     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
22122 _string_0f_2f_compare:
22123     0x11/imm32/alloc-id:fake:payload
22124     # "0f 2f/compare"
22125     0xd/imm32/size
22126     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
22127 _string_21_and_with:  # (payload array byte)
22128     0x11/imm32/alloc-id:fake:payload
22129     # "21/and-with"
22130     0xb/imm32/size
22131     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
22132 _string_23_and:  # (payload array byte)
22133     0x11/imm32/alloc-id:fake:payload
22134     # "23/and"
22135     0x6/imm32/size
22136     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
22137 _string_25_and_with_eax:  # (payload array byte)
22138     0x11/imm32/alloc-id:fake:payload
22139     # "25/and-with-eax"
22140     0xf/imm32/size
22141     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
22142 _string_29_subtract_from:  # (payload array byte)
22143     0x11/imm32/alloc-id:fake:payload
22144     # "29/subtract-from"
22145     0x10/imm32/size
22146     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
22147 _string_2b_subtract:  # (payload array byte)
22148     0x11/imm32/alloc-id:fake:payload
22149     # "2b/subtract"
22150     0xb/imm32/size
22151     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
22152 _string_2d_subtract_from_eax:  # (payload array byte)
22153     0x11/imm32/alloc-id:fake:payload
22154     # "2d/subtract-from-eax"
22155     0x14/imm32/size
22156     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
22157 _string_31_xor_with:  # (payload array byte)
22158     0x11/imm32/alloc-id:fake:payload
22159     # "31/xor-with"
22160     0xb/imm32/size
22161     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
22162 _string_33_xor:  # (payload array byte)
22163     0x11/imm32/alloc-id:fake:payload
22164     # "33/xor"
22165     0x6/imm32/size
22166     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
22167 _string_35_xor_with_eax:  # (payload array byte)
22168     0x11/imm32/alloc-id:fake:payload
22169     # "35/xor-with-eax"
22170     0xf/imm32/size
22171     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
22172 _string_39_compare->:  # (payload array byte)
22173     0x11/imm32/alloc-id:fake:payload
22174     # "39/compare->"
22175     0xc/imm32/size
22176     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
22177 _string_3b_compare<-:  # (payload array byte)
22178     0x11/imm32/alloc-id:fake:payload
22179     # "3b/compare<-"
22180     0xc/imm32/size
22181     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
22182 _string_3d_compare_eax_with:  # (payload array byte)
22183     0x11/imm32/alloc-id:fake:payload
22184     # "3d/compare-eax-with"
22185     0x13/imm32/size
22186     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
22187 _string_40_increment_eax:  # (payload array byte)
22188     0x11/imm32/alloc-id:fake:payload
22189     # "40/increment-eax"
22190     0x10/imm32/size
22191     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
22192 _string_41_increment_ecx:  # (payload array byte)
22193     0x11/imm32/alloc-id:fake:payload
22194     # "41/increment-ecx"
22195     0x10/imm32/size
22196     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
22197 _string_42_increment_edx:  # (payload array byte)
22198     0x11/imm32/alloc-id:fake:payload
22199     # "42/increment-edx"
22200     0x10/imm32/size
22201     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
22202 _string_43_increment_ebx:  # (payload array byte)
22203     0x11/imm32/alloc-id:fake:payload
22204     # "43/increment-ebx"
22205     0x10/imm32/size
22206     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
22207 _string_46_increment_esi:  # (payload array byte)
22208     0x11/imm32/alloc-id:fake:payload
22209     # "46/increment-esi"
22210     0x10/imm32/size
22211     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
22212 _string_47_increment_edi:  # (payload array byte)
22213     0x11/imm32/alloc-id:fake:payload
22214     # "47/increment-edi"
22215     0x10/imm32/size
22216     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
22217 _string_48_decrement_eax:  # (payload array byte)
22218     0x11/imm32/alloc-id:fake:payload
22219     # "48/decrement-eax"
22220     0x10/imm32/size
22221     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
22222 _string_49_decrement_ecx:  # (payload array byte)
22223     0x11/imm32/alloc-id:fake:payload
22224     # "49/decrement-ecx"
22225     0x10/imm32/size
22226     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
22227 _string_4a_decrement_edx:  # (payload array byte)
22228     0x11/imm32/alloc-id:fake:payload
22229     # "4a/decrement-edx"
22230     0x10/imm32/size
22231     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
22232 _string_4b_decrement_ebx:  # (payload array byte)
22233     0x11/imm32/alloc-id:fake:payload
22234     # "4b/decrement-ebx"
22235     0x10/imm32/size
22236     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
22237 _string_4e_decrement_esi:  # (payload array byte)
22238     0x11/imm32/alloc-id:fake:payload
22239     # "4e/decrement-esi"
22240     0x10/imm32/size
22241     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
22242 _string_4f_decrement_edi:  # (payload array byte)
22243     0x11/imm32/alloc-id:fake:payload
22244     # "4f/decrement-edi"
22245     0x10/imm32/size
22246     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
22247 _string_81_subop_add:  # (payload array byte)
22248     0x11/imm32/alloc-id:fake:payload
22249     # "81 0/subop/add"
22250     0xe/imm32/size
22251     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
22252 _string_81_subop_or:  # (payload array byte)
22253     0x11/imm32/alloc-id:fake:payload
22254     # "81 1/subop/or"
22255     0xd/imm32/size
22256     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
22257 _string_81_subop_and:  # (payload array byte)
22258     0x11/imm32/alloc-id:fake:payload
22259     # "81 4/subop/and"
22260     0xe/imm32/size
22261     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
22262 _string_81_subop_subtract:  # (payload array byte)
22263     0x11/imm32/alloc-id:fake:payload
22264     # "81 5/subop/subtract"
22265     0x13/imm32/size
22266     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
22267 _string_81_subop_xor:  # (payload array byte)
22268     0x11/imm32/alloc-id:fake:payload
22269     # "81 6/subop/xor"
22270     0xe/imm32/size
22271     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
22272 _string_81_subop_compare:  # (payload array byte)
22273     0x11/imm32/alloc-id:fake:payload
22274     # "81 7/subop/compare"
22275     0x12/imm32/size
22276     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
22277 _string_89_<-:  # (payload array byte)
22278     0x11/imm32/alloc-id:fake:payload
22279     # "89/<-"
22280     0x5/imm32/size
22281     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
22282 _string_8b_->:  # (payload array byte)
22283     0x11/imm32/alloc-id:fake:payload
22284     # "8b/->"
22285     0x5/imm32/size
22286     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
22287 _string_8a_copy_byte:
22288     0x11/imm32/alloc-id:fake:payload
22289     # "8a/byte->"
22290     0x9/imm32/size
22291     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
22292 _string_88_copy_byte:
22293     0x11/imm32/alloc-id:fake:payload
22294     # "88/byte<-"
22295     0x9/imm32/size
22296     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
22297 _string_8d_copy_address:  # (payload array byte)
22298     0x11/imm32/alloc-id:fake:payload
22299     # "8d/copy-address"
22300     0xf/imm32/size
22301     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
22302 _string_b8_copy_to_eax:  # (payload array byte)
22303     0x11/imm32/alloc-id:fake:payload
22304     # "b8/copy-to-eax"
22305     0xe/imm32/size
22306     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
22307 _string_b9_copy_to_ecx:  # (payload array byte)
22308     0x11/imm32/alloc-id:fake:payload
22309     # "b9/copy-to-ecx"
22310     0xe/imm32/size
22311     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
22312 _string_ba_copy_to_edx:  # (payload array byte)
22313     0x11/imm32/alloc-id:fake:payload
22314     # "ba/copy-to-edx"
22315     0xe/imm32/size
22316     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
22317 _string_bb_copy_to_ebx:  # (payload array byte)
22318     0x11/imm32/alloc-id:fake:payload
22319     # "bb/copy-to-ebx"
22320     0xe/imm32/size
22321     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
22322 _string_be_copy_to_esi:  # (payload array byte)
22323     0x11/imm32/alloc-id:fake:payload
22324     # "be/copy-to-esi"
22325     0xe/imm32/size
22326     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
22327 _string_bf_copy_to_edi:  # (payload array byte)
22328     0x11/imm32/alloc-id:fake:payload
22329     # "bf/copy-to-edi"
22330     0xe/imm32/size
22331     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
22332 _string_c7_subop_copy:  # (payload array byte)
22333     0x11/imm32/alloc-id:fake:payload
22334     # "c7 0/subop/copy"
22335     0xf/imm32/size
22336     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
22337 _string_e9_jump_label:  # (payload array byte)
22338     0x11/imm32/alloc-id:fake:payload
22339     # "e9/jump"
22340     0x7/imm32/size
22341     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
22342 _string_e9_jump_break:  # (payload array byte)
22343     0x11/imm32/alloc-id:fake:payload
22344     # "e9/jump break/disp32"
22345     0x14/imm32/size
22346     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
22347 _string_e9_jump_loop:  # (payload array byte)
22348     0x11/imm32/alloc-id:fake:payload
22349     # "e9/jump loop/disp32"
22350     0x13/imm32/size
22351     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
22352 _string_f7_subop_negate:
22353     0x11/imm32/alloc-id:fake:payload
22354     # "f7 3/subop/negate"
22355     0x11/imm32/size
22356     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
22357 _string_ff_subop_increment:  # (payload array byte)
22358     0x11/imm32/alloc-id:fake:payload
22359     # "ff 0/subop/increment"
22360     0x14/imm32/size
22361     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
22362 _string_ff_subop_decrement:  # (payload array byte)
22363     0x11/imm32/alloc-id:fake:payload
22364     # "ff 1/subop/decrement"
22365     0x14/imm32/size
22366     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
22367 _string_c1_subop_shift_left:  # (payload array byte)
22368     0x11/imm32/alloc-id:fake:payload
22369     # "c1/shift 4/subop/left"
22370     0x15/imm32/size
22371     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
22372 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
22373     0x11/imm32/alloc-id:fake:payload
22374     # "c1/shift 5/subop/right-padding-zeroes"
22375     0x25/imm32/size
22376     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
22377 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
22378     0x11/imm32/alloc-id:fake:payload
22379     # "c1/shift 7/subop/right-preserving-sign"
22380     0x26/imm32/size
22381     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
22382 
22383 Single-int-var-in-mem:  # (payload list var)
22384     0x11/imm32/alloc-id:fake:payload
22385     0x11/imm32/alloc-id:fake
22386     Int-var-in-mem/imm32
22387     0/imm32/next
22388     0/imm32/next
22389 
22390 Int-var-in-mem:  # (payload var)
22391     0x11/imm32/alloc-id:fake:payload
22392     0/imm32/name
22393     0/imm32/name
22394     0x11/imm32/alloc-id:fake
22395     Type-int/imm32
22396     1/imm32/some-block-depth
22397     1/imm32/some-stack-offset
22398     0/imm32/no-register
22399     0/imm32/no-register
22400 
22401 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
22402 Single-byte-var-in-mem:  # (payload list var)
22403     0x11/imm32/alloc-id:fake:payload
22404     0x11/imm32/alloc-id:fake
22405     Byte-var-in-mem/imm32
22406     0/imm32/next
22407     0/imm32/next
22408 
22409 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
22410 Byte-var-in-mem:  # (payload var)
22411     0x11/imm32/alloc-id:fake:payload
22412     0/imm32/name
22413     0/imm32/name
22414     0x11/imm32/alloc-id:fake
22415     Type-byte/imm32
22416     1/imm32/some-block-depth
22417     1/imm32/some-stack-offset
22418     0/imm32/no-register
22419     0/imm32/no-register
22420 
22421 Two-args-int-stack-int-reg:  # (payload list var)
22422     0x11/imm32/alloc-id:fake:payload
22423     0x11/imm32/alloc-id:fake
22424     Int-var-in-mem/imm32
22425     0x11/imm32/alloc-id:fake
22426     Single-int-var-in-some-register/imm32/next
22427 
22428 Two-int-args-in-regs:  # (payload list var)
22429     0x11/imm32/alloc-id:fake:payload
22430     0x11/imm32/alloc-id:fake
22431     Int-var-in-some-register/imm32
22432     0x11/imm32/alloc-id:fake
22433     Single-int-var-in-some-register/imm32/next
22434 
22435 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
22436 Two-args-byte-stack-byte-reg:  # (payload list var)
22437     0x11/imm32/alloc-id:fake:payload
22438     0x11/imm32/alloc-id:fake
22439     Byte-var-in-mem/imm32
22440     0x11/imm32/alloc-id:fake
22441     Single-byte-var-in-some-register/imm32/next
22442 
22443 Two-args-int-reg-int-stack:  # (payload list var)
22444     0x11/imm32/alloc-id:fake:payload
22445     0x11/imm32/alloc-id:fake
22446     Int-var-in-some-register/imm32
22447     0x11/imm32/alloc-id:fake
22448     Single-int-var-in-mem/imm32/next
22449 
22450 Two-args-int-eax-int-literal:  # (payload list var)
22451     0x11/imm32/alloc-id:fake:payload
22452     0x11/imm32/alloc-id:fake
22453     Int-var-in-eax/imm32
22454     0x11/imm32/alloc-id:fake
22455     Single-lit-var/imm32/next
22456 
22457 Int-var-and-literal:  # (payload list var)
22458     0x11/imm32/alloc-id:fake:payload
22459     0x11/imm32/alloc-id:fake
22460     Int-var-in-mem/imm32
22461     0x11/imm32/alloc-id:fake
22462     Single-lit-var/imm32/next
22463 
22464 Int-var-in-register-and-literal:  # (payload list var)
22465     0x11/imm32/alloc-id:fake:payload
22466     0x11/imm32/alloc-id:fake
22467     Int-var-in-some-register/imm32
22468     0x11/imm32/alloc-id:fake
22469     Single-lit-var/imm32/next
22470 
22471 Two-float-args-in-regs:  # (payload list var)
22472     0x11/imm32/alloc-id:fake:payload
22473     0x11/imm32/alloc-id:fake
22474     Float-var-in-some-register/imm32
22475     0x11/imm32/alloc-id:fake
22476     Single-float-var-in-some-register/imm32/next
22477 
22478 Two-args-float-reg-float-stack:  # (payload list var)
22479     0x11/imm32/alloc-id:fake:payload
22480     0x11/imm32/alloc-id:fake
22481     Float-var-in-some-register/imm32
22482     0x11/imm32/alloc-id:fake
22483     Single-float-var-in-mem/imm32/next
22484 
22485 Two-args-float-stack-float-reg:  # (payload list var)
22486     0x11/imm32/alloc-id:fake:payload
22487     0x11/imm32/alloc-id:fake
22488     Float-var-in-mem/imm32
22489     0x11/imm32/alloc-id:fake
22490     Single-float-var-in-some-register/imm32/next
22491 
22492 Single-int-var-in-some-register:  # (payload list var)
22493     0x11/imm32/alloc-id:fake:payload
22494     0x11/imm32/alloc-id:fake
22495     Int-var-in-some-register/imm32
22496     0/imm32/next
22497     0/imm32/next
22498 
22499 Single-addr-var-in-some-register:  # (payload list var)
22500     0x11/imm32/alloc-id:fake:payload
22501     0x11/imm32/alloc-id:fake
22502     Addr-var-in-some-register/imm32
22503     0/imm32/next
22504     0/imm32/next
22505 
22506 Single-byte-var-in-some-register:  # (payload list var)
22507     0x11/imm32/alloc-id:fake:payload
22508     0x11/imm32/alloc-id:fake
22509     Byte-var-in-some-register/imm32
22510     0/imm32/next
22511     0/imm32/next
22512 
22513 Int-var-in-some-register:  # (payload var)
22514     0x11/imm32/alloc-id:fake:payload
22515     0/imm32/name
22516     0/imm32/name
22517     0x11/imm32/alloc-id:fake
22518     Type-int/imm32
22519     1/imm32/some-block-depth
22520     0/imm32/no-stack-offset
22521     0x11/imm32/alloc-id:fake
22522     Any-register/imm32
22523 
22524 Any-register:  # (payload array byte)
22525     0x11/imm32/alloc-id:fake:payload
22526     1/imm32/size
22527     # data
22528     2a/asterisk
22529 
22530 Addr-var-in-some-register:  # (payload var)
22531     0x11/imm32/alloc-id:fake:payload
22532     0/imm32/name
22533     0/imm32/name
22534     0x11/imm32/alloc-id:fake
22535     Type-addr/imm32
22536     1/imm32/some-block-depth
22537     0/imm32/no-stack-offset
22538     0x11/imm32/alloc-id:fake
22539     Any-register/imm32
22540 
22541 Byte-var-in-some-register:  # (payload var)
22542     0x11/imm32/alloc-id:fake:payload
22543     0/imm32/name
22544     0/imm32/name
22545     0x11/imm32/alloc-id:fake
22546     Type-byte/imm32
22547     1/imm32/some-block-depth
22548     0/imm32/no-stack-offset
22549     0x11/imm32/alloc-id:fake
22550     Any-register/imm32
22551 
22552 Single-int-var-in-eax:  # (payload list var)
22553     0x11/imm32/alloc-id:fake:payload
22554     0x11/imm32/alloc-id:fake
22555     Int-var-in-eax/imm32
22556     0/imm32/next
22557     0/imm32/next
22558 
22559 Int-var-in-eax:
22560     0x11/imm32/alloc-id:fake:payload
22561     0/imm32/name
22562     0/imm32/name
22563     0x11/imm32/alloc-id:fake
22564     Type-int/imm32
22565     1/imm32/some-block-depth
22566     0/imm32/no-stack-offset
22567     0x11/imm32/alloc-id:fake
22568     $Register-eax/imm32
22569 
22570 Single-int-var-in-ecx:  # (payload list var)
22571     0x11/imm32/alloc-id:fake:payload
22572     0x11/imm32/alloc-id:fake
22573     Int-var-in-ecx/imm32
22574     0/imm32/next
22575     0/imm32/next
22576 
22577 Int-var-in-ecx:
22578     0x11/imm32/alloc-id:fake:payload
22579     0/imm32/name
22580     0/imm32/name
22581     0x11/imm32/alloc-id:fake
22582     Type-int/imm32
22583     1/imm32/some-block-depth
22584     0/imm32/no-stack-offset
22585     0x11/imm32/alloc-id:fake
22586     $Register-ecx/imm32/register
22587 
22588 Single-int-var-in-edx:  # (payload list var)
22589     0x11/imm32/alloc-id:fake:payload
22590     0x11/imm32/alloc-id:fake
22591     Int-var-in-edx/imm32
22592     0/imm32/next
22593     0/imm32/next
22594 
22595 Int-var-in-edx:  # (payload list var)
22596     0x11/imm32/alloc-id:fake:payload
22597     0/imm32/name
22598     0/imm32/name
22599     0x11/imm32/alloc-id:fake
22600     Type-int/imm32
22601     1/imm32/some-block-depth
22602     0/imm32/no-stack-offset
22603     0x11/imm32/alloc-id:fake
22604     $Register-edx/imm32/register
22605 
22606 Single-int-var-in-ebx:  # (payload list var)
22607     0x11/imm32/alloc-id:fake:payload
22608     0x11/imm32/alloc-id:fake
22609     Int-var-in-ebx/imm32
22610     0/imm32/next
22611     0/imm32/next
22612 
22613 Int-var-in-ebx:  # (payload list var)
22614     0x11/imm32/alloc-id:fake:payload
22615     0/imm32/name
22616     0/imm32/name
22617     0x11/imm32/alloc-id:fake
22618     Type-int/imm32
22619     1/imm32/some-block-depth
22620     0/imm32/no-stack-offset
22621     0x11/imm32/alloc-id:fake
22622     $Register-ebx/imm32/register
22623 
22624 Single-int-var-in-esi:  # (payload list var)
22625     0x11/imm32/alloc-id:fake:payload
22626     0x11/imm32/alloc-id:fake
22627     Int-var-in-esi/imm32
22628     0/imm32/next
22629     0/imm32/next
22630 
22631 Int-var-in-esi:  # (payload list var)
22632     0x11/imm32/alloc-id:fake:payload
22633     0/imm32/name
22634     0/imm32/name
22635     0x11/imm32/alloc-id:fake
22636     Type-int/imm32
22637     1/imm32/some-block-depth
22638     0/imm32/no-stack-offset
22639     0x11/imm32/alloc-id:fake
22640     $Register-esi/imm32/register
22641 
22642 Single-int-var-in-edi:  # (payload list var)
22643     0x11/imm32/alloc-id:fake:payload
22644     0x11/imm32/alloc-id:fake
22645     Int-var-in-edi/imm32
22646     0/imm32/next
22647     0/imm32/next
22648 
22649 Int-var-in-edi:  # (payload list var)
22650     0x11/imm32/alloc-id:fake:payload
22651     0/imm32/name
22652     0/imm32/name
22653     0x11/imm32/alloc-id:fake
22654     Type-int/imm32
22655     1/imm32/some-block-depth
22656     0/imm32/no-stack-offset
22657     0x11/imm32/alloc-id:fake
22658     $Register-edi/imm32/register
22659 
22660 Single-lit-var:  # (payload list var)
22661     0x11/imm32/alloc-id:fake:payload
22662     0x11/imm32/alloc-id:fake
22663     Lit-var/imm32
22664     0/imm32/next
22665     0/imm32/next
22666 
22667 Lit-var:  # (payload var)
22668     0x11/imm32/alloc-id:fake:payload
22669     0/imm32/name
22670     0/imm32/name
22671     0x11/imm32/alloc-id:fake
22672     Type-literal/imm32
22673     1/imm32/some-block-depth
22674     0/imm32/no-stack-offset
22675     0/imm32/no-register
22676     0/imm32/no-register
22677 
22678 Single-float-var-in-mem:  # (payload list var)
22679     0x11/imm32/alloc-id:fake:payload
22680     0x11/imm32/alloc-id:fake
22681     Float-var-in-mem/imm32
22682     0/imm32/next
22683     0/imm32/next
22684 
22685 Float-var-in-mem:  # (payload var)
22686     0x11/imm32/alloc-id:fake:payload
22687     0/imm32/name
22688     0/imm32/name
22689     0x11/imm32/alloc-id:fake
22690     Type-float/imm32
22691     1/imm32/some-block-depth
22692     1/imm32/some-stack-offset
22693     0/imm32/no-register
22694     0/imm32/no-register
22695 
22696 Single-float-var-in-some-register:  # (payload list var)
22697     0x11/imm32/alloc-id:fake:payload
22698     0x11/imm32/alloc-id:fake
22699     Float-var-in-some-register/imm32
22700     0/imm32/next
22701     0/imm32/next
22702 
22703 Float-var-in-some-register:  # (payload var)
22704     0x11/imm32/alloc-id:fake:payload
22705     0/imm32/name
22706     0/imm32/name
22707     0x11/imm32/alloc-id:fake
22708     Type-float/imm32
22709     1/imm32/some-block-depth
22710     0/imm32/no-stack-offset
22711     0x11/imm32/alloc-id:fake
22712     Any-register/imm32
22713 
22714 Type-int:  # (payload type-tree)
22715     0x11/imm32/alloc-id:fake:payload
22716     1/imm32/is-atom
22717     1/imm32/value:int
22718     0/imm32/left:unused
22719     0/imm32/right:null
22720     0/imm32/right:null
22721 
22722 Type-literal:  # (payload type-tree)
22723     0x11/imm32/alloc-id:fake:payload
22724     1/imm32/is-atom
22725     0/imm32/value:literal
22726     0/imm32/left:unused
22727     0/imm32/right:null
22728     0/imm32/right:null
22729 
22730 Type-addr:  # (payload type-tree)
22731     0x11/imm32/alloc-id:fake:payload
22732     1/imm32/is-atom
22733     2/imm32/value:addr
22734     0/imm32/left:unused
22735     0/imm32/right:null
22736     0/imm32/right:null
22737 
22738 Type-byte:  # (payload type-tree)
22739     0x11/imm32/alloc-id:fake:payload
22740     1/imm32/is-atom
22741     8/imm32/value:byte
22742     0/imm32/left:unused
22743     0/imm32/right:null
22744     0/imm32/right:null
22745 
22746 Type-float:  # (payload type-tree)
22747     0x11/imm32/alloc-id:fake:payload
22748     1/imm32/is-atom
22749     0xf/imm32/value:float
22750     0/imm32/left:unused
22751     0/imm32/right:null
22752     0/imm32/right:null
22753 
22754 == code
22755 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
22756     # . prologue
22757     55/push-ebp
22758     89/<- %ebp 4/r32/esp
22759     # . save registers
22760     50/push-eax
22761     51/push-ecx
22762     # ecx = primitive
22763     8b/-> *(ebp+0x10) 1/r32/ecx
22764     # emit primitive name
22765     (emit-indent *(ebp+8) *Curr-block-depth)
22766     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
22767     (write-buffered *(ebp+8) %eax)
22768     # emit rm32 if necessary
22769     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
22770     # emit xm32 if necessary
22771     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
22772     # emit r32 if necessary
22773     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
22774     # emit x32 if necessary
22775     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
22776     # emit imm32 if necessary
22777     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
22778     # emit imm8 if necessary
22779     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
22780     # emit disp32 if necessary
22781     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
22782     (write-buffered *(ebp+8) Newline)
22783 $emit-subx-primitive:end:
22784     # . restore registers
22785     59/pop-to-ecx
22786     58/pop-to-eax
22787     # . epilogue
22788     89/<- %esp 5/r32/ebp
22789     5d/pop-to-ebp
22790     c3/return
22791 
22792 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
22793     # . prologue
22794     55/push-ebp
22795     89/<- %ebp 4/r32/esp
22796     # . save registers
22797     50/push-eax
22798     # if (l == 0) return
22799     81 7/subop/compare *(ebp+0xc) 0/imm32
22800     74/jump-if-= $emit-subx-rm32:end/disp8
22801     # var v/eax: (addr stmt-var)
22802     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
22803     (emit-subx-var-as-rm32 *(ebp+8) %eax)
22804 $emit-subx-rm32:end:
22805     # . restore registers
22806     58/pop-to-eax
22807     # . epilogue
22808     89/<- %esp 5/r32/ebp
22809     5d/pop-to-ebp
22810     c3/return
22811 
22812 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)
22813     # . prologue
22814     55/push-ebp
22815     89/<- %ebp 4/r32/esp
22816     # . save registers
22817     51/push-ecx
22818     # eax = l
22819     8b/-> *(ebp+0xc) 0/r32/eax
22820     # ecx = stmt
22821     8b/-> *(ebp+8) 1/r32/ecx
22822     # if (l == 1) return stmt->inouts
22823     {
22824       3d/compare-eax-and 1/imm32
22825       75/jump-if-!= break/disp8
22826 $get-stmt-operand-from-arg-location:1:
22827       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22828       eb/jump $get-stmt-operand-from-arg-location:end/disp8
22829     }
22830     # if (l == 2) return stmt->inouts->next
22831     {
22832       3d/compare-eax-and 2/imm32
22833       75/jump-if-!= break/disp8
22834 $get-stmt-operand-from-arg-location:2:
22835       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22836       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22837       eb/jump $get-stmt-operand-from-arg-location:end/disp8
22838     }
22839     # if (l == 3) return stmt->outputs
22840     {
22841       3d/compare-eax-and 3/imm32
22842       75/jump-if-!= break/disp8
22843 $get-stmt-operand-from-arg-location:3:
22844       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22845       eb/jump $get-stmt-operand-from-arg-location:end/disp8
22846     }
22847     # abort
22848     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
22849 $get-stmt-operand-from-arg-location:end:
22850     # . restore registers
22851     59/pop-to-ecx
22852     # . epilogue
22853     89/<- %esp 5/r32/ebp
22854     5d/pop-to-ebp
22855     c3/return
22856 
22857 $get-stmt-operand-from-arg-location:abort:
22858     # error("invalid arg-location " eax)
22859     (write-buffered *(ebp+0x10) "invalid arg-location ")
22860     (write-int32-hex-buffered *(ebp+0x10) %eax)
22861     (write-buffered *(ebp+0x10) Newline)
22862     (flush *(ebp+0x10))
22863     (stop *(ebp+0x14) 1)
22864     # never gets here
22865 
22866 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
22867     # . prologue
22868     55/push-ebp
22869     89/<- %ebp 4/r32/esp
22870     # . save registers
22871     50/push-eax
22872     51/push-ecx
22873     # if (l == 0) return
22874     81 7/subop/compare *(ebp+0xc) 0/imm32
22875     0f 84/jump-if-= $emit-subx-r32:end/disp32
22876     # var v/eax: (addr stmt-var)
22877     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
22878     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22879     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22880 #?     (write-buffered Stderr "looking up ")
22881 #?     (write-buffered Stderr %eax)
22882 #?     (write-buffered Stderr Newline)
22883 #?     (flush Stderr)
22884     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
22885     (write-buffered *(ebp+8) Space)
22886     (write-int32-hex-buffered *(ebp+8) *eax)
22887     (write-buffered *(ebp+8) "/r32")
22888 $emit-subx-r32:end:
22889     # . restore registers
22890     59/pop-to-ecx
22891     58/pop-to-eax
22892     # . epilogue
22893     89/<- %esp 5/r32/ebp
22894     5d/pop-to-ebp
22895     c3/return
22896 
22897 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
22898     # . prologue
22899     55/push-ebp
22900     89/<- %ebp 4/r32/esp
22901     # . save registers
22902     50/push-eax
22903     51/push-ecx
22904     # if (l == 0) return
22905     81 7/subop/compare *(ebp+0xc) 0/imm32
22906     0f 84/jump-if-= $emit-subx-x32:end/disp32
22907     # var v/eax: (addr stmt-var)
22908     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
22909     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22910     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
22911 #?     (write-buffered Stderr "looking up ")
22912 #?     (write-buffered Stderr %eax)
22913 #?     (write-buffered Stderr Newline)
22914 #?     (flush Stderr)
22915     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
22916     (write-buffered *(ebp+8) Space)
22917     (write-int32-hex-buffered *(ebp+8) *eax)
22918     (write-buffered *(ebp+8) "/x32")
22919 $emit-subx-x32:end:
22920     # . restore registers
22921     59/pop-to-ecx
22922     58/pop-to-eax
22923     # . epilogue
22924     89/<- %esp 5/r32/ebp
22925     5d/pop-to-ebp
22926     c3/return
22927 
22928 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
22929     # . prologue
22930     55/push-ebp
22931     89/<- %ebp 4/r32/esp
22932     # . save registers
22933     50/push-eax
22934     51/push-ecx
22935     # if (l == 0) return
22936     81 7/subop/compare *(ebp+0xc) 0/imm32
22937     0f 84/jump-if-= $emit-subx-imm32:end/disp32
22938     # var v/eax: (handle var)
22939     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
22940     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22941     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22942     (write-buffered *(ebp+8) Space)
22943     (write-buffered *(ebp+8) %eax)
22944     (write-buffered *(ebp+8) "/imm32")
22945 $emit-subx-imm32:end:
22946     # . restore registers
22947     59/pop-to-ecx
22948     58/pop-to-eax
22949     # . epilogue
22950     89/<- %esp 5/r32/ebp
22951     5d/pop-to-ebp
22952     c3/return
22953 
22954 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
22955     # . prologue
22956     55/push-ebp
22957     89/<- %ebp 4/r32/esp
22958     # . save registers
22959     50/push-eax
22960     51/push-ecx
22961     # if (l == 0) return
22962     81 7/subop/compare *(ebp+0xc) 0/imm32
22963     0f 84/jump-if-= $emit-subx-imm32:end/disp32
22964     # var v/eax: (handle var)
22965     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
22966     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22967     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22968     (write-buffered *(ebp+8) Space)
22969     (write-buffered *(ebp+8) %eax)
22970     (write-buffered *(ebp+8) "/imm8")
22971 $emit-subx-imm8:end:
22972     # . restore registers
22973     59/pop-to-ecx
22974     58/pop-to-eax
22975     # . epilogue
22976     89/<- %esp 5/r32/ebp
22977     5d/pop-to-ebp
22978     c3/return
22979 
22980 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
22981     # . prologue
22982     55/push-ebp
22983     89/<- %ebp 4/r32/esp
22984     # . save registers
22985     50/push-eax
22986     51/push-ecx
22987     # if (location == 0) return
22988     81 7/subop/compare *(ebp+0xc) 0/imm32
22989     0f 84/jump-if-= $emit-subx-disp32:end/disp32
22990     # var v/eax: (addr stmt-var)
22991     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
22992     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22993     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22994     (write-buffered *(ebp+8) Space)
22995     (write-buffered *(ebp+8) %eax)
22996     # hack: if instruction operation starts with "break", emit ":break"
22997     # var name/ecx: (addr array byte) = lookup(stmt->operation)
22998     8b/-> *(ebp+0x10) 0/r32/eax
22999     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23000     89/<- %ecx 0/r32/eax
23001     {
23002       (string-starts-with? %ecx "break")  # => eax
23003       3d/compare-eax-and 0/imm32/false
23004       74/jump-if-= break/disp8
23005       (write-buffered *(ebp+8) ":break")
23006     }
23007     # hack: if instruction operation starts with "loop", emit ":loop"
23008     {
23009       (string-starts-with? %ecx "loop")  # => eax
23010       3d/compare-eax-and 0/imm32/false
23011       74/jump-if-= break/disp8
23012       (write-buffered *(ebp+8) ":loop")
23013     }
23014     (write-buffered *(ebp+8) "/disp32")
23015 $emit-subx-disp32:end:
23016     # . restore registers
23017     59/pop-to-ecx
23018     58/pop-to-eax
23019     # . epilogue
23020     89/<- %esp 5/r32/ebp
23021     5d/pop-to-ebp
23022     c3/return
23023 
23024 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
23025     # . prologue
23026     55/push-ebp
23027     89/<- %ebp 4/r32/esp
23028     # . save registers
23029     50/push-eax
23030     51/push-ecx
23031     #
23032     (emit-indent *(ebp+8) *Curr-block-depth)
23033     (write-buffered *(ebp+8) "(")
23034     # ecx = stmt
23035     8b/-> *(ebp+0xc) 1/r32/ecx
23036     # - emit function name
23037     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
23038     (write-buffered *(ebp+8) %eax)
23039     # - emit arguments
23040     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
23041     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23042     {
23043       # if (curr == null) break
23044       3d/compare-eax-and 0/imm32
23045       74/jump-if-= break/disp8
23046       #
23047       (emit-subx-call-operand *(ebp+8) %eax)
23048       # curr = lookup(curr->next)
23049       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23050       eb/jump loop/disp8
23051     }
23052     #
23053     (write-buffered *(ebp+8) ")\n")
23054 $emit-call:end:
23055     # . restore registers
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 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
23064     # shares code with emit-subx-var-as-rm32
23065     # . prologue
23066     55/push-ebp
23067     89/<- %ebp 4/r32/esp
23068     # . save registers
23069     50/push-eax
23070     51/push-ecx
23071     56/push-esi
23072     # ecx = s
23073     8b/-> *(ebp+0xc) 1/r32/ecx
23074     # var operand/esi: (addr var) = lookup(s->value)
23075     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23076     89/<- %esi 0/r32/eax
23077     # if (operand->register && !s->is-deref?) emit "%__"
23078     {
23079 $emit-subx-call-operand:check-for-register-direct:
23080       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
23081       74/jump-if-= break/disp8
23082       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23083       75/jump-if-!= break/disp8
23084 $emit-subx-call-operand:register-direct:
23085       (write-buffered *(ebp+8) " %")
23086       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
23087       (write-buffered *(ebp+8) %eax)
23088       e9/jump $emit-subx-call-operand:end/disp32
23089     }
23090     # else if (operand->register && s->is-deref?) emit "*__"
23091     {
23092 $emit-subx-call-operand:check-for-register-indirect:
23093       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
23094       74/jump-if-= break/disp8
23095       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23096       74/jump-if-= break/disp8
23097 $emit-subx-call-operand:register-indirect:
23098       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
23099       e9/jump $emit-subx-call-operand:end/disp32
23100     }
23101     # else if (operand->stack-offset) emit "*(ebp+__)"
23102     {
23103       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
23104       74/jump-if-= break/disp8
23105 $emit-subx-call-operand:stack:
23106       (emit-subx-call-operand-stack *(ebp+8) %esi)
23107       e9/jump $emit-subx-call-operand:end/disp32
23108     }
23109     # else if (operand->type == literal) emit "__"
23110     {
23111       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
23112       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-left
23113       75/jump-if-!= break/disp8
23114 $emit-subx-call-operand:literal:
23115       (write-buffered *(ebp+8) Space)
23116       (lookup *esi *(esi+4))  # Var-name Var-name => eax
23117       (write-buffered *(ebp+8) %eax)
23118     }
23119 $emit-subx-call-operand:end:
23120     # . restore registers
23121     5e/pop-to-esi
23122     59/pop-to-ecx
23123     58/pop-to-eax
23124     # . epilogue
23125     89/<- %esp 5/r32/ebp
23126     5d/pop-to-ebp
23127     c3/return
23128 
23129 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
23130     # . prologue
23131     55/push-ebp
23132     89/<- %ebp 4/r32/esp
23133     # . save registers
23134     50/push-eax
23135     51/push-ecx
23136     56/push-esi
23137     # esi = v
23138     8b/-> *(ebp+0xc) 6/r32/esi
23139     # var size/ecx: int = size-of-deref(v)
23140     (size-of-deref %esi)  # => eax
23141     89/<- %ecx 0/r32/eax
23142     # var reg-name/esi: (addr array byte) = lookup(v->register)
23143     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
23144     89/<- %esi 0/r32/eax
23145     # TODO: assert size is a multiple of 4
23146     # var i/eax: int = 0
23147     b8/copy-to-eax 0/imm32
23148     {
23149 $emit-subx-call-operand-register-indirect:loop:
23150       # if (i >= size) break
23151       39/compare %eax 1/r32/ecx
23152       7d/jump-if->= break/disp8
23153       # emit " *(" v->register "+" i ")"
23154       (write-buffered *(ebp+8) " *(")
23155       (write-buffered *(ebp+8) %esi)
23156       (write-buffered *(ebp+8) "+")
23157       (write-int32-hex-buffered *(ebp+8) %eax)
23158       (write-buffered *(ebp+8) ")")
23159       # i += 4
23160       05/add-to-eax 4/imm32
23161       #
23162       eb/jump loop/disp8
23163     }
23164 $emit-subx-call-operand-register-indirect:end:
23165     # . restore registers
23166     5e/pop-to-esi
23167     59/pop-to-ecx
23168     58/pop-to-eax
23169     # . epilogue
23170     89/<- %esp 5/r32/ebp
23171     5d/pop-to-ebp
23172     c3/return
23173 
23174 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
23175     # . prologue
23176     55/push-ebp
23177     89/<- %ebp 4/r32/esp
23178     # . save registers
23179     50/push-eax
23180     51/push-ecx
23181     56/push-esi
23182     # esi = v
23183     8b/-> *(ebp+0xc) 6/r32/esi
23184     # var curr/ecx: int = v->offset
23185     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
23186     # var max/eax: int = v->offset + size-of(v)
23187     (size-of %esi)  # => eax
23188     # TODO: assert size is a multiple of 4
23189     01/add-to %eax 1/r32/ecx
23190     {
23191 $emit-subx-call-operand-stack:loop:
23192       # if (curr >= max) break
23193       39/compare %ecx 0/r32/eax
23194       7d/jump-if->= break/disp8
23195       # emit " *(ebp+" curr ")"
23196       (write-buffered *(ebp+8) " *(ebp+")
23197       (write-int32-hex-buffered *(ebp+8) %ecx)
23198       (write-buffered *(ebp+8) ")")
23199       # i += 4
23200       81 0/subop/add %ecx 4/imm32
23201       #
23202       eb/jump loop/disp8
23203     }
23204 $emit-subx-call-operand-stack:end:
23205     # . restore registers
23206     5e/pop-to-esi
23207     59/pop-to-ecx
23208     58/pop-to-eax
23209     # . epilogue
23210     89/<- %esp 5/r32/ebp
23211     5d/pop-to-ebp
23212     c3/return
23213 
23214 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
23215     # . prologue
23216     55/push-ebp
23217     89/<- %ebp 4/r32/esp
23218     # . save registers
23219     50/push-eax
23220     51/push-ecx
23221     56/push-esi
23222     # ecx = s
23223     8b/-> *(ebp+0xc) 1/r32/ecx
23224     # var operand/esi: (addr var) = lookup(s->value)
23225     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23226     89/<- %esi 0/r32/eax
23227     # if (operand->register && s->is-deref?) emit "*__"
23228     {
23229 $emit-subx-var-as-rm32:check-for-register-indirect:
23230       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
23231       74/jump-if-= break/disp8
23232       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23233       74/jump-if-= break/disp8
23234 $emit-subx-var-as-rm32:register-indirect:
23235       (write-buffered *(ebp+8) " *")
23236       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
23237       (write-buffered *(ebp+8) %eax)
23238       e9/jump $emit-subx-var-as-rm32:end/disp32
23239     }
23240     # if (operand->register && !s->is-deref?) emit "%__"
23241     {
23242 $emit-subx-var-as-rm32:check-for-register-direct:
23243       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
23244       74/jump-if-= break/disp8
23245       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23246       75/jump-if-!= break/disp8
23247 $emit-subx-var-as-rm32:register-direct:
23248       (write-buffered *(ebp+8) " %")
23249       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
23250       (write-buffered *(ebp+8) %eax)
23251       e9/jump $emit-subx-var-as-rm32:end/disp32
23252     }
23253     # else if (operand->stack-offset) emit "*(ebp+__)"
23254     {
23255       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
23256       74/jump-if-= break/disp8
23257 $emit-subx-var-as-rm32:stack:
23258       (write-buffered *(ebp+8) Space)
23259       (write-buffered *(ebp+8) "*(ebp+")
23260       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
23261       (write-buffered *(ebp+8) ")")
23262     }
23263 $emit-subx-var-as-rm32:end:
23264     # . restore registers
23265     5e/pop-to-esi
23266     59/pop-to-ecx
23267     58/pop-to-eax
23268     # . epilogue
23269     89/<- %esp 5/r32/ebp
23270     5d/pop-to-ebp
23271     c3/return
23272 
23273 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
23274     # . prologue
23275     55/push-ebp
23276     89/<- %ebp 4/r32/esp
23277     # . save registers
23278     51/push-ecx
23279     # var curr/ecx: (addr primitive) = primitives
23280     8b/-> *(ebp+8) 1/r32/ecx
23281     {
23282 $find-matching-primitive:loop:
23283       # if (curr == null) break
23284       81 7/subop/compare %ecx 0/imm32
23285       74/jump-if-= break/disp8
23286       # if match(curr, stmt) return curr
23287       {
23288         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
23289         3d/compare-eax-and 0/imm32/false
23290         74/jump-if-= break/disp8
23291         89/<- %eax 1/r32/ecx
23292         eb/jump $find-matching-primitive:end/disp8
23293       }
23294 $find-matching-primitive:next-primitive:
23295       # curr = curr->next
23296       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
23297       89/<- %ecx 0/r32/eax
23298       #
23299       e9/jump loop/disp32
23300     }
23301     # return null
23302     b8/copy-to-eax 0/imm32
23303 $find-matching-primitive:end:
23304     # . restore registers
23305     59/pop-to-ecx
23306     # . epilogue
23307     89/<- %esp 5/r32/ebp
23308     5d/pop-to-ebp
23309     c3/return
23310 
23311 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
23312     # A mu stmt matches a primitive if the name matches, all the inout vars
23313     # match, and all the output vars match.
23314     # Vars match if types match and registers match.
23315     # In addition, a stmt output matches a primitive's output if types match
23316     # and the primitive has a wildcard register.
23317     # . prologue
23318     55/push-ebp
23319     89/<- %ebp 4/r32/esp
23320     # . save registers
23321     51/push-ecx
23322     52/push-edx
23323     53/push-ebx
23324     56/push-esi
23325     57/push-edi
23326     # ecx = stmt
23327     8b/-> *(ebp+8) 1/r32/ecx
23328     # edx = primitive
23329     8b/-> *(ebp+0xc) 2/r32/edx
23330     {
23331 $mu-stmt-matches-primitive?:check-name:
23332       # if (primitive->name != stmt->operation) return false
23333       # . var esi: (addr array byte) = lookup(stmt->operation)
23334       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
23335       89/<- %esi 0/r32/eax
23336       # . var edi: (addr array byte) = lookup(primitive->name)
23337       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
23338 #?       (write-buffered Stderr %eax)
23339 #?       (write-buffered Stderr Newline)
23340 #?       (flush Stderr)
23341       89/<- %edi 0/r32/eax
23342       (string-equal? %esi %edi)  # => eax
23343       3d/compare-eax-and 0/imm32/false
23344       75/jump-if-!= break/disp8
23345       b8/copy-to-eax 0/imm32
23346       e9/jump $mu-stmt-matches-primitive?:end/disp32
23347     }
23348     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
23349     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23350     89/<- %esi 0/r32/eax
23351     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
23352     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
23353     89/<- %edi 0/r32/eax
23354     {
23355 $mu-stmt-matches-primitive?:inouts-loop:
23356       # if (curr == 0 && curr2 == 0) move on to check outputs
23357       {
23358 $mu-stmt-matches-primitive?:check-both-inouts-null:
23359         81 7/subop/compare %esi 0/imm32
23360         75/jump-if-!= break/disp8
23361 $mu-stmt-matches-primitive?:stmt-inout-null:
23362         81 7/subop/compare %edi 0/imm32
23363         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
23364 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
23365         # return false
23366         b8/copy-to-eax 0/imm32/false
23367         e9/jump $mu-stmt-matches-primitive?:end/disp32
23368       }
23369       # if (curr2 == 0) return false
23370       {
23371 $mu-stmt-matches-primitive?:check-prim-inout-null:
23372         81 7/subop/compare %edi 0/imm32
23373         75/jump-if-!= break/disp8
23374 $mu-stmt-matches-primitive?:prim-inout-null:
23375         b8/copy-to-eax 0/imm32/false
23376         e9/jump $mu-stmt-matches-primitive?:end/disp32
23377       }
23378       # if (curr != curr2) return false
23379       {
23380 $mu-stmt-matches-primitive?:check-inouts-match:
23381         (lookup *edi *(edi+4))  # List-value List-value => eax
23382         (operand-matches-primitive? %esi %eax)  # => eax
23383         3d/compare-eax-and 0/imm32/false
23384         75/jump-if-!= break/disp8
23385 $mu-stmt-matches-primitive?:inouts-match:
23386         b8/copy-to-eax 0/imm32/false
23387         e9/jump $mu-stmt-matches-primitive?:end/disp32
23388       }
23389 $mu-stmt-matches-primitive?:next-inout:
23390       # curr = lookup(curr->next)
23391       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23392       89/<- %esi 0/r32/eax
23393       # curr2 = lookup(curr2->next)
23394       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23395       89/<- %edi 0/r32/eax
23396       #
23397       e9/jump loop/disp32
23398     }
23399 $mu-stmt-matches-primitive?:check-outputs:
23400     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
23401     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23402     89/<- %esi 0/r32/eax
23403     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
23404     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
23405     89/<- %edi 0/r32/eax
23406     {
23407 $mu-stmt-matches-primitive?:outputs-loop:
23408       # if (curr == 0) return (curr2 == 0)
23409       {
23410 $mu-stmt-matches-primitive?:check-both-outputs-null:
23411         81 7/subop/compare %esi 0/imm32
23412         75/jump-if-!= break/disp8
23413         {
23414 $mu-stmt-matches-primitive?:stmt-output-null:
23415           81 7/subop/compare %edi 0/imm32
23416           75/jump-if-!= break/disp8
23417 $mu-stmt-matches-primitive?:both-outputs-null:
23418           # return true
23419           b8/copy-to-eax 1/imm32
23420           e9/jump $mu-stmt-matches-primitive?:end/disp32
23421         }
23422 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
23423         # return false
23424         b8/copy-to-eax 0/imm32
23425         e9/jump $mu-stmt-matches-primitive?:end/disp32
23426       }
23427       # if (curr2 == 0) return false
23428       {
23429 $mu-stmt-matches-primitive?:check-prim-output-null:
23430         81 7/subop/compare %edi 0/imm32
23431         75/jump-if-!= break/disp8
23432 $mu-stmt-matches-primitive?:prim-output-is-null:
23433         b8/copy-to-eax 0/imm32
23434         e9/jump $mu-stmt-matches-primitive?:end/disp32
23435       }
23436       # if (curr != curr2) return false
23437       {
23438 $mu-stmt-matches-primitive?:check-outputs-match:
23439         (lookup *edi *(edi+4))  # List-value List-value => eax
23440         (operand-matches-primitive? %esi %eax)  # => eax
23441         3d/compare-eax-and 0/imm32/false
23442         75/jump-if-!= break/disp8
23443 $mu-stmt-matches-primitive?:outputs-match:
23444         b8/copy-to-eax 0/imm32
23445         e9/jump $mu-stmt-matches-primitive?:end/disp32
23446       }
23447 $mu-stmt-matches-primitive?:next-output:
23448       # curr = lookup(curr->next)
23449       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23450       89/<- %esi 0/r32/eax
23451       # curr2 = lookup(curr2->next)
23452       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
23453       89/<- %edi 0/r32/eax
23454       #
23455       e9/jump loop/disp32
23456     }
23457 $mu-stmt-matches-primitive?:return-true:
23458     b8/copy-to-eax 1/imm32
23459 $mu-stmt-matches-primitive?:end:
23460     # . restore registers
23461     5f/pop-to-edi
23462     5e/pop-to-esi
23463     5b/pop-to-ebx
23464     5a/pop-to-edx
23465     59/pop-to-ecx
23466     # . epilogue
23467     89/<- %esp 5/r32/ebp
23468     5d/pop-to-ebp
23469     c3/return
23470 
23471 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
23472     # . prologue
23473     55/push-ebp
23474     89/<- %ebp 4/r32/esp
23475     # . save registers
23476     51/push-ecx
23477     52/push-edx
23478     53/push-ebx
23479     56/push-esi
23480     57/push-edi
23481     # ecx = s
23482     8b/-> *(ebp+8) 1/r32/ecx
23483     # var var/esi: (addr var) = lookup(s->value)
23484     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23485     89/<- %esi 0/r32/eax
23486     # edi = prim-var
23487     8b/-> *(ebp+0xc) 7/r32/edi
23488 $operand-matches-primitive?:check-type:
23489     # if !category-match?(var->type, prim-var->type) return false
23490     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
23491     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
23492     89/<- %ebx 0/r32/eax
23493     # . if s is deref, vtype = vtype->right
23494     {
23495       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23496       74/jump-if-= break/disp8
23497 $operand-matches-primitive?:is-deref:
23498       # . var t/eax: (addr type)
23499       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23500       # . if !t->is-atom? t = t->left
23501       81 7/subop/compare *eax 0/imm32/false
23502       {
23503         75/jump-if-!= break/disp8
23504         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23505       }
23506       # .
23507       89/<- %ebx 0/r32/eax
23508     }
23509     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
23510     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
23511     (subx-type-category-match? %ebx %eax)  # => eax
23512     3d/compare-eax-and 0/imm32/false
23513     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
23514     {
23515 $operand-matches-primitive?:check-register:
23516       # if prim-var is in memory and var is in register but dereference, match
23517       {
23518         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
23519         0f 85/jump-if-!= break/disp32
23520         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
23521         74/jump-if-= break/disp8
23522         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23523         74/jump-if-= break/disp8
23524 $operand-matches-primitive?:var-deref-match:
23525         e9/jump $operand-matches-primitive?:return-true/disp32
23526       }
23527       # if prim-var is in register and var is in register but dereference, no match
23528       {
23529         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
23530         0f 84/jump-if-= break/disp32
23531         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
23532         0f 84/jump-if-= break/disp32
23533         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23534         74/jump-if-= break/disp8
23535 $operand-matches-primitive?:var-deref-no-match:
23536         e9/jump $operand-matches-primitive?:return-false/disp32
23537       }
23538       # return false if var->register doesn't match prim-var->register
23539       {
23540         # if register addresses are equal, it's a match
23541         # var vreg/ebx: (addr array byte) = lookup(var->register)
23542         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
23543         89/<- %ebx 0/r32/eax
23544         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
23545         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
23546         89/<- %ecx 0/r32/eax
23547         # if (vreg == preg) break
23548         39/compare %ecx 3/r32/ebx
23549         74/jump-if-= break/disp8
23550 $operand-matches-primitive?:var-register-no-match:
23551         # if either address is 0, return false
23552         81 7/subop/compare %ebx 0/imm32
23553         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
23554         81 7/subop/compare %ecx 0/imm32
23555         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
23556         # if prim-var->register is wildcard, it's a match
23557         (string-equal? %ecx "*")  # Any-register => eax
23558         3d/compare-eax-and 0/imm32/false
23559         75/jump-if-!= break/disp8
23560 $operand-matches-primitive?:wildcard-no-match:
23561         # if string contents aren't equal, return false
23562         (string-equal? %ecx %ebx)  # => eax
23563         3d/compare-eax-and 0/imm32/false
23564         74/jump-if-= $operand-matches-primitive?:return-false/disp8
23565       }
23566     }
23567 $operand-matches-primitive?:return-true:
23568     b8/copy-to-eax 1/imm32/true
23569     eb/jump $operand-matches-primitive?:end/disp8
23570 $operand-matches-primitive?:return-false:
23571     b8/copy-to-eax 0/imm32/false
23572 $operand-matches-primitive?:end:
23573     # . restore registers
23574     5f/pop-to-edi
23575     5e/pop-to-esi
23576     5b/pop-to-ebx
23577     5a/pop-to-edx
23578     59/pop-to-ecx
23579     # . epilogue
23580     89/<- %esp 5/r32/ebp
23581     5d/pop-to-ebp
23582     c3/return
23583 
23584 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
23585     # . prologue
23586     55/push-ebp
23587     89/<- %ebp 4/r32/esp
23588     # . save registers
23589     51/push-ecx
23590     # var curr/ecx: (handle function) = functions
23591     8b/-> *(ebp+8) 1/r32/ecx
23592     {
23593       # if (curr == null) break
23594       81 7/subop/compare %ecx 0/imm32
23595       74/jump-if-= break/disp8
23596 #?       (write-buffered Stderr "iter\n")
23597 #?       (flush Stderr)
23598       # if match(stmt, curr) return curr
23599       {
23600         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
23601         3d/compare-eax-and 0/imm32/false
23602         74/jump-if-= break/disp8
23603         89/<- %eax 1/r32/ecx
23604         eb/jump $find-matching-function:end/disp8
23605       }
23606       # curr = curr->next
23607       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
23608       89/<- %ecx 0/r32/eax
23609       #
23610       eb/jump loop/disp8
23611     }
23612     # return null
23613     b8/copy-to-eax 0/imm32
23614 $find-matching-function:end:
23615     # . restore registers
23616     59/pop-to-ecx
23617     # . epilogue
23618     89/<- %esp 5/r32/ebp
23619     5d/pop-to-ebp
23620     c3/return
23621 
23622 # Just compare names; user-defined functions don't support overloading yet.
23623 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
23624     # . prologue
23625     55/push-ebp
23626     89/<- %ebp 4/r32/esp
23627     # . save registers
23628     51/push-ecx
23629     # return function->name == stmt->operation
23630     # ecx = lookup(stmt->operation)
23631     8b/-> *(ebp+8) 0/r32/eax
23632     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
23633     89/<- %ecx 0/r32/eax
23634     # eax = lookup(function->name)
23635     8b/-> *(ebp+0xc) 0/r32/eax
23636     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23637     (string-equal? %eax %ecx)  # => eax
23638 $mu-stmt-matches-function?:end:
23639     # . restore registers
23640     59/pop-to-ecx
23641     # . epilogue
23642     89/<- %esp 5/r32/ebp
23643     5d/pop-to-ebp
23644     c3/return
23645 
23646 # Type-checking happens elsewhere. This method is for selecting between
23647 # primitives.
23648 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
23649     # . prologue
23650     55/push-ebp
23651     89/<- %ebp 4/r32/esp
23652     # . save registers
23653     51/push-ecx
23654     # var cata/ecx: int = type-category(a)
23655     (type-category *(ebp+8))  # => eax
23656     89/<- %ecx 0/r32/eax
23657     # var catb/eax: int = type-category(b)
23658     (type-category *(ebp+0xc))  # => eax
23659     # return cata == catb
23660     39/compare %eax 1/r32/ecx
23661     0f 94/set-byte-if-= %al
23662     81 4/subop/and %eax 0xff/imm32
23663 $subx-type-category-match?:end:
23664     # . restore registers
23665     59/pop-to-ecx
23666     # . epilogue
23667     89/<- %esp 5/r32/ebp
23668     5d/pop-to-ebp
23669     c3/return
23670 
23671 type-category:  # a: (addr type-tree) -> result/eax: int
23672     # . prologue
23673     55/push-ebp
23674     89/<- %ebp 4/r32/esp
23675     # . save registers
23676     51/push-ecx
23677     # var lit?/ecx: boolean = is-literal-type?(a)
23678     (is-simple-mu-type? *(ebp+8) 0)  # => eax
23679     89/<- %ecx 0/r32/eax
23680     # var float?/eax: int = is-float?(a)
23681     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
23682     # set bits for lit? and float?
23683     c1/shift 4/subop/left %ecx 1/imm8
23684     09/or %eax 1/r32/ecx
23685 $type-category:end:
23686     # . restore registers
23687     59/pop-to-ecx
23688     # . epilogue
23689     89/<- %esp 5/r32/ebp
23690     5d/pop-to-ebp
23691     c3/return
23692 
23693 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
23694     # . prologue
23695     55/push-ebp
23696     89/<- %ebp 4/r32/esp
23697     # . save registers
23698     51/push-ecx
23699     # ecx = n
23700     8b/-> *(ebp+0xc) 1/r32/ecx
23701     # return (a->value == n)
23702     8b/-> *(ebp+8) 0/r32/eax
23703     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
23704     0f 94/set-byte-if-= %al
23705     81 4/subop/and %eax 0xff/imm32
23706 $is-simple-mu-type?:end:
23707     # . restore registers
23708     59/pop-to-ecx
23709     # . epilogue
23710     89/<- %esp 5/r32/ebp
23711     5d/pop-to-ebp
23712     c3/return
23713 
23714 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
23715     # . prologue
23716     55/push-ebp
23717     89/<- %ebp 4/r32/esp
23718     # eax = a
23719     8b/-> *(ebp+8) 0/r32/eax
23720     # if (!a->is-atom?) a = a->left
23721     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23722     {
23723       75/jump-if-!= break/disp8
23724       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23725     }
23726     # return (a->value == addr)
23727     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
23728     0f 94/set-byte-if-= %al
23729     81 4/subop/and %eax 0xff/imm32
23730 $is-mu-addr-type?:end:
23731     # . epilogue
23732     89/<- %esp 5/r32/ebp
23733     5d/pop-to-ebp
23734     c3/return
23735 
23736 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
23737     # . prologue
23738     55/push-ebp
23739     89/<- %ebp 4/r32/esp
23740     # eax = a
23741     8b/-> *(ebp+8) 0/r32/eax
23742     # if (!a->is-atom?) a = a->left
23743     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23744     {
23745       75/jump-if-!= break/disp8
23746       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23747     }
23748     # return (a->value == array)
23749     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
23750     0f 94/set-byte-if-= %al
23751     81 4/subop/and %eax 0xff/imm32
23752 $is-mu-array-type?:end:
23753     # . epilogue
23754     89/<- %esp 5/r32/ebp
23755     5d/pop-to-ebp
23756     c3/return
23757 
23758 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
23759     # . prologue
23760     55/push-ebp
23761     89/<- %ebp 4/r32/esp
23762     # eax = a
23763     8b/-> *(ebp+8) 0/r32/eax
23764     # if (!a->is-atom?) a = a->left
23765     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23766     {
23767       75/jump-if-!= break/disp8
23768       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23769     }
23770     # return (a->value == stream)
23771     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
23772     0f 94/set-byte-if-= %al
23773     81 4/subop/and %eax 0xff/imm32
23774 $is-mu-stream-type?:end:
23775     # . epilogue
23776     89/<- %esp 5/r32/ebp
23777     5d/pop-to-ebp
23778     c3/return
23779 
23780 test-emit-subx-stmt-primitive:
23781     # Primitive operation on a variable on the stack.
23782     #   increment foo
23783     # =>
23784     #   ff 0/subop/increment *(ebp-8)
23785     #
23786     # There's a variable on the var stack as follows:
23787     #   name: 'foo'
23788     #   type: int
23789     #   stack-offset: -8
23790     #
23791     # There's a primitive with this info:
23792     #   name: 'increment'
23793     #   inouts: int/mem
23794     #   value: 'ff 0/subop/increment'
23795     #
23796     # . prologue
23797     55/push-ebp
23798     89/<- %ebp 4/r32/esp
23799     # setup
23800     (clear-stream _test-output-stream)
23801     (clear-stream $_test-output-buffered-file->buffer)
23802     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
23803 $test-emit-subx-stmt-primitive:initialize-type:
23804     # var type/ecx: (payload type-tree) = int
23805     68/push 0/imm32/right:null
23806     68/push 0/imm32/right:null
23807     68/push 0/imm32/left:unused
23808     68/push 1/imm32/value:int
23809     68/push 1/imm32/is-atom?:true
23810     68/push 0x11/imm32/alloc-id:fake:payload
23811     89/<- %ecx 4/r32/esp
23812 $test-emit-subx-stmt-primitive:initialize-var:
23813     # var var-foo/ecx: (payload var) = var(type)
23814     68/push 0/imm32/no-register
23815     68/push 0/imm32/no-register
23816     68/push -8/imm32/stack-offset
23817     68/push 1/imm32/block-depth
23818     51/push-ecx/type
23819     68/push 0x11/imm32/alloc-id:fake
23820     68/push 0/imm32/name
23821     68/push 0/imm32/name
23822     68/push 0x11/imm32/alloc-id:fake:payload
23823     89/<- %ecx 4/r32/esp
23824 $test-emit-subx-stmt-primitive:initialize-var-name:
23825     # var-foo->name = "foo"
23826     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
23827     (copy-array Heap "foo" %eax)
23828 $test-emit-subx-stmt-primitive:initialize-stmt-var:
23829     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
23830     68/push 0/imm32/is-deref:false
23831     68/push 0/imm32/next
23832     68/push 0/imm32/next
23833     51/push-ecx/var-foo
23834     68/push 0x11/imm32/alloc-id:fake
23835     68/push 0x11/imm32/alloc-id:fake:payload
23836     89/<- %ebx 4/r32/esp
23837 $test-emit-subx-stmt-primitive:initialize-stmt:
23838     # var stmt/esi: (addr statement)
23839     68/push 0/imm32/no-outputs
23840     68/push 0/imm32/no-outputs
23841     53/push-ebx/inouts
23842     68/push 0x11/imm32/alloc-id:fake
23843     68/push 0/imm32/operation
23844     68/push 0/imm32/operation
23845     68/push 1/imm32/tag
23846     89/<- %esi 4/r32/esp
23847 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
23848     # stmt->operation = "increment"
23849     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
23850     (copy-array Heap "increment" %eax)
23851 $test-emit-subx-stmt-primitive:initialize-primitive:
23852     # var primitives/ebx: (addr primitive)
23853     68/push 0/imm32/next
23854     68/push 0/imm32/next
23855     68/push 0/imm32/no-x32
23856     68/push 0/imm32/no-xm32
23857     68/push 0/imm32/no-disp32
23858     68/push 0/imm32/no-imm8
23859     68/push 0/imm32/no-imm32
23860     68/push 0/imm32/no-r32
23861     68/push 1/imm32/rm32-is-first-inout
23862     68/push 0/imm32/subx-name
23863     68/push 0/imm32/subx-name
23864     68/push 0/imm32/no-outputs
23865     68/push 0/imm32/no-outputs
23866     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
23867     68/push 0x11/imm32/alloc-id:fake
23868     68/push 0/imm32/name
23869     68/push 0/imm32/name
23870     89/<- %ebx 4/r32/esp
23871 $test-emit-subx-stmt-primitive:initialize-primitive-name:
23872     # primitives->name = "increment"
23873     (copy-array Heap "increment" %ebx)  # Primitive-name
23874 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
23875     # primitives->subx-name = "ff 0/subop/increment"
23876     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
23877     (copy-array Heap "ff 0/subop/increment" %eax)
23878     # convert
23879     c7 0/subop/copy *Curr-block-depth 0/imm32
23880     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
23881     (flush _test-output-buffered-file)
23882 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
23888     # check output
23889     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
23890     # . epilogue
23891     89/<- %esp 5/r32/ebp
23892     5d/pop-to-ebp
23893     c3/return
23894 
23895 test-emit-subx-stmt-primitive-register:
23896     # Primitive operation on a variable in a register.
23897     #   foo <- increment
23898     # =>
23899     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
23900     #
23901     # There's a variable on the var stack as follows:
23902     #   name: 'foo'
23903     #   type: int
23904     #   register: 'eax'
23905     #
23906     # There's a primitive with this info:
23907     #   name: 'increment'
23908     #   out: int/reg
23909     #   value: 'ff 0/subop/increment'
23910     #
23911     # . prologue
23912     55/push-ebp
23913     89/<- %ebp 4/r32/esp
23914     # setup
23915     (clear-stream _test-output-stream)
23916     (clear-stream $_test-output-buffered-file->buffer)
23917 $test-emit-subx-stmt-primitive-register:initialize-type:
23918     # var type/ecx: (payload type-tree) = int
23919     68/push 0/imm32/right:null
23920     68/push 0/imm32/right:null
23921     68/push 0/imm32/left:unused
23922     68/push 1/imm32/value:int
23923     68/push 1/imm32/is-atom?:true
23924     68/push 0x11/imm32/alloc-id:fake:payload
23925     89/<- %ecx 4/r32/esp
23926 $test-emit-subx-stmt-primitive-register:initialize-var:
23927     # var var-foo/ecx: (payload var)
23928     68/push 0/imm32/register
23929     68/push 0/imm32/register
23930     68/push 0/imm32/no-stack-offset
23931     68/push 1/imm32/block-depth
23932     51/push-ecx
23933     68/push 0x11/imm32/alloc-id:fake
23934     68/push 0/imm32/name
23935     68/push 0/imm32/name
23936     68/push 0x11/imm32/alloc-id:fake:payload
23937     89/<- %ecx 4/r32/esp
23938 $test-emit-subx-stmt-primitive-register:initialize-var-name:
23939     # var-foo->name = "foo"
23940     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
23941     (copy-array Heap "foo" %eax)
23942 $test-emit-subx-stmt-primitive-register:initialize-var-register:
23943     # var-foo->register = "eax"
23944     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
23945     (copy-array Heap "eax" %eax)
23946 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
23947     # var operand/ebx: (payload stmt-var)
23948     68/push 0/imm32/is-deref:false
23949     68/push 0/imm32/next
23950     68/push 0/imm32/next
23951     51/push-ecx/var-foo
23952     68/push 0x11/imm32/alloc-id:fake
23953     68/push 0x11/imm32/alloc-id:fake:payload
23954     89/<- %ebx 4/r32/esp
23955 $test-emit-subx-stmt-primitive-register:initialize-stmt:
23956     # var stmt/esi: (addr statement)
23957     53/push-ebx/outputs
23958     68/push 0x11/imm32/alloc-id:fake
23959     68/push 0/imm32/no-inouts
23960     68/push 0/imm32/no-inouts
23961     68/push 0/imm32/operation
23962     68/push 0/imm32/operation
23963     68/push 1/imm32
23964     89/<- %esi 4/r32/esp
23965 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
23966     # stmt->operation = "increment"
23967     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
23968     (copy-array Heap "increment" %eax)
23969 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
23970     # var formal-var/ebx: (payload var)
23971     68/push 0/imm32/register
23972     68/push 0/imm32/register
23973     68/push 0/imm32/no-stack-offset
23974     68/push 1/imm32/block-depth
23975     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
23976     68/push 0x11/imm32/alloc-id:fake
23977     68/push 0/imm32/name
23978     68/push 0/imm32/name
23979     68/push 0x11/imm32/alloc-id:fake:payload
23980     89/<- %ebx 4/r32/esp
23981 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
23982     # formal-var->name = "dummy"
23983     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
23984     (copy-array Heap "dummy" %eax)
23985 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
23986     # formal-var->register = "*"
23987     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
23988     (copy-array Heap "*" %eax)  # Any-register
23989 $test-emit-subx-stmt-primitive-register:initialize-var-list:
23990     # var formal-outputs/ebx: (payload list var)
23991     68/push 0/imm32/next
23992     68/push 0/imm32/next
23993     53/push-ebx/formal-var
23994     68/push 0x11/imm32/alloc-id:fake
23995     68/push 0x11/imm32/alloc-id:fake:payload
23996     89/<- %ebx 4/r32/esp
23997 $test-emit-subx-stmt-primitive-register:initialize-primitive:
23998     # var primitives/ebx: (addr primitive)
23999     68/push 0/imm32/next
24000     68/push 0/imm32/next
24001     68/push 0/imm32/no-x32
24002     68/push 0/imm32/no-xm32
24003     68/push 0/imm32/no-disp32
24004     68/push 0/imm32/no-imm8
24005     68/push 0/imm32/no-imm32
24006     68/push 0/imm32/no-r32
24007     68/push 3/imm32/rm32-is-first-output
24008     68/push 0/imm32/subx-name
24009     68/push 0/imm32/subx-name
24010     53/push-ebx/outputs
24011     68/push 0x11/imm32/alloc-id:fake
24012     68/push 0/imm32/no-inouts
24013     68/push 0/imm32/no-inouts
24014     68/push 0/imm32/name
24015     68/push 0/imm32/name
24016     89/<- %ebx 4/r32/esp
24017 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
24018     # primitives->name = "increment"
24019     (copy-array Heap "increment" %ebx)  # Primitive-name
24020 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
24021     # primitives->subx-name = "ff 0/subop/increment"
24022     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
24023     (copy-array Heap "ff 0/subop/increment" %eax)
24024     # convert
24025     c7 0/subop/copy *Curr-block-depth 0/imm32
24026     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
24027     (flush _test-output-buffered-file)
24028 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24034     # check output
24035     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
24036     # . epilogue
24037     89/<- %esp 5/r32/ebp
24038     5d/pop-to-ebp
24039     c3/return
24040 
24041 test-emit-subx-stmt-select-primitive:
24042     # Select the right primitive between overloads.
24043     #   foo <- increment
24044     # =>
24045     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
24046     #
24047     # There's a variable on the var stack as follows:
24048     #   name: 'foo'
24049     #   type: int
24050     #   register: 'eax'
24051     #
24052     # There's two primitives, as follows:
24053     #   - name: 'increment'
24054     #     out: int/reg
24055     #     value: 'ff 0/subop/increment'
24056     #   - name: 'increment'
24057     #     inout: int/mem
24058     #     value: 'ff 0/subop/increment'
24059     #
24060     # . prologue
24061     55/push-ebp
24062     89/<- %ebp 4/r32/esp
24063     # setup
24064     (clear-stream _test-output-stream)
24065     (clear-stream $_test-output-buffered-file->buffer)
24066 $test-emit-subx-stmt-select-primitive:initialize-type:
24067     # var type/ecx: (payload type-tree) = int
24068     68/push 0/imm32/right:null
24069     68/push 0/imm32/right:null
24070     68/push 0/imm32/left:unused
24071     68/push 1/imm32/value:int
24072     68/push 1/imm32/is-atom?:true
24073     68/push 0x11/imm32/alloc-id:fake:payload
24074     89/<- %ecx 4/r32/esp
24075 $test-emit-subx-stmt-select-primitive:initialize-var:
24076     # var var-foo/ecx: (payload var)
24077     68/push 0/imm32/register
24078     68/push 0/imm32/register
24079     68/push 0/imm32/no-stack-offset
24080     68/push 1/imm32/block-depth
24081     51/push-ecx
24082     68/push 0x11/imm32/alloc-id:fake
24083     68/push 0/imm32/name
24084     68/push 0/imm32/name
24085     68/push 0x11/imm32/alloc-id:fake:payload
24086     89/<- %ecx 4/r32/esp
24087 $test-emit-subx-stmt-select-primitive:initialize-var-name:
24088     # var-foo->name = "foo"
24089     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24090     (copy-array Heap "foo" %eax)
24091 $test-emit-subx-stmt-select-primitive:initialize-var-register:
24092     # var-foo->register = "eax"
24093     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24094     (copy-array Heap "eax" %eax)
24095 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
24096     # var operand/ebx: (payload stmt-var)
24097     68/push 0/imm32/is-deref:false
24098     68/push 0/imm32/next
24099     68/push 0/imm32/next
24100     51/push-ecx/var-foo
24101     68/push 0x11/imm32/alloc-id:fake
24102     68/push 0x11/imm32/alloc-id:fake:payload
24103     89/<- %ebx 4/r32/esp
24104 $test-emit-subx-stmt-select-primitive:initialize-stmt:
24105     # var stmt/esi: (addr statement)
24106     53/push-ebx/outputs
24107     68/push 0x11/imm32/alloc-id:fake
24108     68/push 0/imm32/no-inouts
24109     68/push 0/imm32/no-inouts
24110     68/push 0/imm32/operation
24111     68/push 0/imm32/operation
24112     68/push 1/imm32
24113     89/<- %esi 4/r32/esp
24114 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
24115     # stmt->operation = "increment"
24116     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24117     (copy-array Heap "increment" %eax)
24118 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
24119     # var formal-var/ebx: (payload var)
24120     68/push 0/imm32/register
24121     68/push 0/imm32/register
24122     68/push 0/imm32/no-stack-offset
24123     68/push 1/imm32/block-depth
24124     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
24125     68/push 0x11/imm32/alloc-id:fake
24126     68/push 0/imm32/name
24127     68/push 0/imm32/name
24128     68/push 0x11/imm32/alloc-id:fake:payload
24129     89/<- %ebx 4/r32/esp
24130 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
24131     # formal-var->name = "dummy"
24132     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
24133     (copy-array Heap "dummy" %eax)
24134 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
24135     # formal-var->register = "*"
24136     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
24137     (copy-array Heap "*" %eax)  # Any-register
24138 $test-emit-subx-stmt-select-primitive:initialize-var-list:
24139     # var formal-outputs/ebx: (payload list var)
24140     68/push 0/imm32/next
24141     68/push 0/imm32/next
24142     53/push-ebx/formal-var
24143     68/push 0x11/imm32/alloc-id:fake
24144     68/push 0x11/imm32/alloc-id:fake:payload
24145     89/<- %ebx 4/r32/esp
24146 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
24147     # var primitive2/edi: (payload primitive)
24148     68/push 0/imm32/next
24149     68/push 0/imm32/next
24150     68/push 0/imm32/no-x32
24151     68/push 0/imm32/no-xm32
24152     68/push 0/imm32/no-disp32
24153     68/push 0/imm32/no-imm8
24154     68/push 0/imm32/no-imm32
24155     68/push 0/imm32/no-r32
24156     68/push 3/imm32/rm32-is-first-output
24157     68/push 0/imm32/subx-name
24158     68/push 0/imm32/subx-name
24159     53/push-ebx/outputs
24160     68/push 0x11/imm32/alloc-id:fake
24161     68/push 0/imm32/no-inouts
24162     68/push 0/imm32/no-inouts
24163     68/push 0/imm32/name
24164     68/push 0/imm32/name
24165     68/push 0x11/imm32/alloc-id:fake:payload
24166     89/<- %edi 4/r32/esp
24167 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
24168     # primitives->name = "increment"
24169     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
24170     (copy-array Heap "increment" %eax)
24171 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
24172     # primitives->subx-name = "ff 0/subop/increment"
24173     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
24174     (copy-array Heap "ff 0/subop/increment" %eax)
24175 $test-emit-subx-stmt-select-primitive:initialize-primitive:
24176     # var primitives/ebx: (addr primitive)
24177     57/push-edi
24178     68/push 0x11/imm32/alloc-id:fake
24179     68/push 0/imm32/no-x32
24180     68/push 0/imm32/no-xm32
24181     68/push 0/imm32/no-disp32
24182     68/push 0/imm32/no-imm8
24183     68/push 0/imm32/no-imm32
24184     68/push 0/imm32/no-r32
24185     68/push 1/imm32/rm32-is-first-inout
24186     68/push 0/imm32/subx-name
24187     68/push 0/imm32/subx-name
24188     68/push 0/imm32/no-outputs
24189     68/push 0/imm32/no-outputs
24190     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
24191     68/push 0x11/imm32/alloc-id:fake
24192     68/push 0/imm32/name
24193     68/push 0/imm32/name
24194     89/<- %ebx 4/r32/esp
24195 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
24196     # primitives->name = "increment"
24197     (copy-array Heap "increment" %ebx)  # Primitive-name
24198 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
24199     # primitives->subx-name = "ff 0/subop/increment"
24200     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
24201     (copy-array Heap "ff 0/subop/increment" %eax)
24202     # convert
24203     c7 0/subop/copy *Curr-block-depth 0/imm32
24204     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
24205     (flush _test-output-buffered-file)
24206 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24212     # check output
24213     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
24214     # . epilogue
24215     89/<- %esp 5/r32/ebp
24216     5d/pop-to-ebp
24217     c3/return
24218 
24219 test-emit-subx-stmt-select-primitive-2:
24220     # Select the right primitive between overloads.
24221     #   increment foo
24222     # =>
24223     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
24224     #
24225     # There's a variable on the var stack as follows:
24226     #   name: 'foo'
24227     #   type: int
24228     #   register: 'eax'
24229     #
24230     # There's two primitives, as follows:
24231     #   - name: 'increment'
24232     #     out: int/reg
24233     #     value: 'ff 0/subop/increment'
24234     #   - name: 'increment'
24235     #     inout: int/mem
24236     #     value: 'ff 0/subop/increment'
24237     #
24238     # . prologue
24239     55/push-ebp
24240     89/<- %ebp 4/r32/esp
24241     # setup
24242     (clear-stream _test-output-stream)
24243     (clear-stream $_test-output-buffered-file->buffer)
24244 $test-emit-subx-stmt-select-primitive-2:initialize-type:
24245     # var type/ecx: (payload type-tree) = int
24246     68/push 0/imm32/right:null
24247     68/push 0/imm32/right:null
24248     68/push 0/imm32/left:unused
24249     68/push 1/imm32/value:int
24250     68/push 1/imm32/is-atom?:true
24251     68/push 0x11/imm32/alloc-id:fake:payload
24252     89/<- %ecx 4/r32/esp
24253 $test-emit-subx-stmt-select-primitive-2:initialize-var:
24254     # var var-foo/ecx: (payload var)
24255     68/push 0/imm32/register
24256     68/push 0/imm32/register
24257     68/push 0/imm32/no-stack-offset
24258     68/push 1/imm32/block-depth
24259     51/push-ecx
24260     68/push 0x11/imm32/alloc-id:fake
24261     68/push 0/imm32/name
24262     68/push 0/imm32/name
24263     68/push 0x11/imm32/alloc-id:fake:payload
24264     89/<- %ecx 4/r32/esp
24265 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
24266     # var-foo->name = "foo"
24267     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24268     (copy-array Heap "foo" %eax)
24269 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
24270     # var-foo->register = "eax"
24271     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24272     (copy-array Heap "eax" %eax)
24273 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
24274     # var operand/ebx: (payload stmt-var)
24275     68/push 0/imm32/is-deref:false
24276     68/push 0/imm32/next
24277     68/push 0/imm32/next
24278     51/push-ecx/var-foo
24279     68/push 0x11/imm32/alloc-id:fake
24280     68/push 0x11/imm32/alloc-id:fake:payload
24281     89/<- %ebx 4/r32/esp
24282 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
24283     # var stmt/esi: (addr statement)
24284     68/push 0/imm32/no-outputs
24285     68/push 0/imm32/no-outputs
24286     53/push-ebx/inouts
24287     68/push 0x11/imm32/alloc-id:fake
24288     68/push 0/imm32/operation
24289     68/push 0/imm32/operation
24290     68/push 1/imm32
24291     89/<- %esi 4/r32/esp
24292 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
24293     # stmt->operation = "increment"
24294     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24295     (copy-array Heap "increment" %eax)
24296 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
24297     # var formal-var/ebx: (payload var)
24298     68/push 0/imm32/register
24299     68/push 0/imm32/register
24300     68/push 0/imm32/no-stack-offset
24301     68/push 1/imm32/block-depth
24302     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
24303     68/push 0x11/imm32/alloc-id:fake
24304     68/push 0/imm32/name
24305     68/push 0/imm32/name
24306     68/push 0x11/imm32/alloc-id:fake:payload
24307     89/<- %ebx 4/r32/esp
24308 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
24309     # formal-var->name = "dummy"
24310     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
24311     (copy-array Heap "dummy" %eax)
24312 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
24313     # formal-var->register = "*"
24314     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
24315     (copy-array Heap "*" %eax)  # Any-register
24316 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
24317     # var formal-outputs/ebx: (payload list stmt-var)
24318     68/push 0/imm32/next
24319     68/push 0/imm32/next
24320     53/push-ebx/formal-var
24321     68/push 0x11/imm32/alloc-id:fake
24322     68/push 0x11/imm32/alloc-id:fake:payload
24323     89/<- %ebx 4/r32/esp
24324 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
24325     # var primitive2/edi: (payload primitive)
24326     68/push 0/imm32/next
24327     68/push 0/imm32/next
24328     68/push 0/imm32/no-x32
24329     68/push 0/imm32/no-xm32
24330     68/push 0/imm32/no-disp32
24331     68/push 0/imm32/no-imm8
24332     68/push 0/imm32/no-imm32
24333     68/push 0/imm32/no-r32
24334     68/push 3/imm32/rm32-is-first-output
24335     68/push 0/imm32/subx-name
24336     68/push 0/imm32/subx-name
24337     53/push-ebx/outputs
24338     68/push 0x11/imm32/alloc-id:fake
24339     68/push 0/imm32/no-inouts
24340     68/push 0/imm32/no-inouts
24341     68/push 0/imm32/name
24342     68/push 0/imm32/name
24343     68/push 0x11/imm32/alloc-id:fake:payload
24344     89/<- %edi 4/r32/esp
24345 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
24346     # primitives->name = "increment"
24347     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
24348     (copy-array Heap "increment" %eax)
24349 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
24350     # primitives->subx-name = "ff 0/subop/increment"
24351     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
24352     (copy-array Heap "ff 0/subop/increment" %eax)
24353 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
24354     # var primitives/ebx: (addr primitive)
24355     57/push-edi
24356     68/push 0x11/imm32/alloc-id:fake
24357     68/push 0/imm32/no-x32
24358     68/push 0/imm32/no-xm32
24359     68/push 0/imm32/no-disp32
24360     68/push 0/imm32/no-imm8
24361     68/push 0/imm32/no-imm32
24362     68/push 0/imm32/no-r32
24363     68/push 1/imm32/rm32-is-first-inout
24364     68/push 0/imm32/subx-name
24365     68/push 0/imm32/subx-name
24366     68/push 0/imm32/no-outputs
24367     68/push 0/imm32/no-outputs
24368     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
24369     68/push 0x11/imm32/alloc-id:fake
24370     68/push 0/imm32/name
24371     68/push 0/imm32/name
24372     89/<- %ebx 4/r32/esp
24373 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
24374     # primitives->name = "increment"
24375     (copy-array Heap "increment" %ebx)  # Primitive-name
24376 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
24377     # primitives->subx-name = "ff 0/subop/increment"
24378     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
24379     (copy-array Heap "ff 0/subop/increment" %eax)
24380     # convert
24381     c7 0/subop/copy *Curr-block-depth 0/imm32
24382     (emit-subx-stmt _test-output-buffered-file %esi %ebx Stderr 0)
24383     (flush _test-output-buffered-file)
24384 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24390     # check output
24391     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
24392     # . epilogue
24393     89/<- %esp 5/r32/ebp
24394     5d/pop-to-ebp
24395     c3/return
24396 
24397 test-increment-register:
24398     # Select the right register between overloads.
24399     #   foo <- increment
24400     # =>
24401     #   50/increment-eax
24402     #
24403     # There's a variable on the var stack as follows:
24404     #   name: 'foo'
24405     #   type: int
24406     #   register: 'eax'
24407     #
24408     # Primitives are the global definitions.
24409     #
24410     # . prologue
24411     55/push-ebp
24412     89/<- %ebp 4/r32/esp
24413     # setup
24414     (clear-stream _test-output-stream)
24415     (clear-stream $_test-output-buffered-file->buffer)
24416 $test-increment-register:initialize-type:
24417     # var type/ecx: (payload type-tree) = int
24418     68/push 0/imm32/right:null
24419     68/push 0/imm32/right:null
24420     68/push 0/imm32/left:unused
24421     68/push 1/imm32/value:int
24422     68/push 1/imm32/is-atom?:true
24423     68/push 0x11/imm32/alloc-id:fake:payload
24424     89/<- %ecx 4/r32/esp
24425 $test-increment-register:initialize-var:
24426     # var var-foo/ecx: (payload var)
24427     68/push 0/imm32/register
24428     68/push 0/imm32/register
24429     68/push 0/imm32/no-stack-offset
24430     68/push 1/imm32/block-depth
24431     51/push-ecx
24432     68/push 0x11/imm32/alloc-id:fake
24433     68/push 0/imm32/name
24434     68/push 0/imm32/name
24435     68/push 0x11/imm32/alloc-id:fake:payload
24436     89/<- %ecx 4/r32/esp
24437 $test-increment-register:initialize-var-name:
24438     # var-foo->name = "foo"
24439     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24440     (copy-array Heap "foo" %eax)
24441 $test-increment-register:initialize-var-register:
24442     # var-foo->register = "eax"
24443     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24444     (copy-array Heap "eax" %eax)
24445 $test-increment-register:initialize-stmt-var:
24446     # var operand/ebx: (payload stmt-var)
24447     68/push 0/imm32/is-deref:false
24448     68/push 0/imm32/next
24449     68/push 0/imm32/next
24450     51/push-ecx/var-foo
24451     68/push 0x11/imm32/alloc-id:fake
24452     68/push 0x11/imm32/alloc-id:fake:payload
24453     89/<- %ebx 4/r32/esp
24454 $test-increment-register:initialize-stmt:
24455     # var stmt/esi: (addr statement)
24456     53/push-ebx/outputs
24457     68/push 0x11/imm32/alloc-id:fake
24458     68/push 0/imm32/no-inouts
24459     68/push 0/imm32/no-inouts
24460     68/push 0/imm32/operation
24461     68/push 0/imm32/operation
24462     68/push 1/imm32
24463     89/<- %esi 4/r32/esp
24464 $test-increment-register:initialize-stmt-operation:
24465     # stmt->operation = "increment"
24466     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24467     (copy-array Heap "increment" %eax)
24468     # convert
24469     c7 0/subop/copy *Curr-block-depth 0/imm32
24470     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
24471     (flush _test-output-buffered-file)
24472 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24478     # check output
24479     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
24480     # . epilogue
24481     89/<- %esp 5/r32/ebp
24482     5d/pop-to-ebp
24483     c3/return
24484 
24485 test-add-reg-to-reg:
24486     #   var1/reg <- add var2/reg
24487     # =>
24488     #   01/add-to %var1 var2
24489     #
24490     # . prologue
24491     55/push-ebp
24492     89/<- %ebp 4/r32/esp
24493     # setup
24494     (clear-stream _test-output-stream)
24495     (clear-stream $_test-output-buffered-file->buffer)
24496 $test-add-reg-to-reg:initialize-type:
24497     # var type/ecx: (payload type-tree) = int
24498     68/push 0/imm32/right:null
24499     68/push 0/imm32/right:null
24500     68/push 0/imm32/left:unused
24501     68/push 1/imm32/value:int
24502     68/push 1/imm32/is-atom?:true
24503     68/push 0x11/imm32/alloc-id:fake:payload
24504     89/<- %ecx 4/r32/esp
24505 $test-add-reg-to-reg:initialize-var1:
24506     # var var1/ecx: (payload var)
24507     68/push 0/imm32/register
24508     68/push 0/imm32/register
24509     68/push 0/imm32/no-stack-offset
24510     68/push 1/imm32/block-depth
24511     51/push-ecx
24512     68/push 0x11/imm32/alloc-id:fake
24513     68/push 0/imm32/name
24514     68/push 0/imm32/name
24515     68/push 0x11/imm32/alloc-id:fake:payload
24516     89/<- %ecx 4/r32/esp
24517 $test-add-reg-to-reg:initialize-var1-name:
24518     # var1->name = "var1"
24519     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24520     (copy-array Heap "var1" %eax)
24521 $test-add-reg-to-reg:initialize-var1-register:
24522     # var1->register = "eax"
24523     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24524     (copy-array Heap "eax" %eax)
24525 $test-add-reg-to-reg:initialize-var2:
24526     # var var2/edx: (payload var)
24527     68/push 0/imm32/register
24528     68/push 0/imm32/register
24529     68/push 0/imm32/no-stack-offset
24530     68/push 1/imm32/block-depth
24531     ff 6/subop/push *(ecx+0x10)
24532     68/push 0x11/imm32/alloc-id:fake
24533     68/push 0/imm32/name
24534     68/push 0/imm32/name
24535     68/push 0x11/imm32/alloc-id:fake:payload
24536     89/<- %edx 4/r32/esp
24537 $test-add-reg-to-reg:initialize-var2-name:
24538     # var2->name = "var2"
24539     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
24540     (copy-array Heap "var2" %eax)
24541 $test-add-reg-to-reg:initialize-var2-register:
24542     # var2->register = "ecx"
24543     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
24544     (copy-array Heap "ecx" %eax)
24545 $test-add-reg-to-reg:initialize-inouts:
24546     # var inouts/esi: (payload stmt-var) = [var2]
24547     68/push 0/imm32/is-deref:false
24548     68/push 0/imm32/next
24549     68/push 0/imm32/next
24550     52/push-edx/var2
24551     68/push 0x11/imm32/alloc-id:fake
24552     68/push 0x11/imm32/alloc-id:fake:payload
24553     89/<- %esi 4/r32/esp
24554 $test-add-reg-to-reg:initialize-outputs:
24555     # var outputs/edi: (payload stmt-var) = [var1]
24556     68/push 0/imm32/is-deref:false
24557     68/push 0/imm32/next
24558     68/push 0/imm32/next
24559     51/push-ecx/var1
24560     68/push 0x11/imm32/alloc-id:fake
24561     68/push 0x11/imm32/alloc-id:fake:payload
24562     89/<- %edi 4/r32/esp
24563 $test-add-reg-to-reg:initialize-stmt:
24564     # var stmt/esi: (addr statement)
24565     68/push 0/imm32/next
24566     68/push 0/imm32/next
24567     57/push-edi/outputs
24568     68/push 0x11/imm32/alloc-id:fake
24569     56/push-esi/inouts
24570     68/push 0x11/imm32/alloc-id:fake
24571     68/push 0/imm32/operation
24572     68/push 0/imm32/operation
24573     68/push 1/imm32/tag:stmt1
24574     89/<- %esi 4/r32/esp
24575 $test-add-reg-to-reg:initialize-stmt-operation:
24576     # stmt->operation = "add"
24577     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24578     (copy-array Heap "add" %eax)
24579     # convert
24580     c7 0/subop/copy *Curr-block-depth 0/imm32
24581     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
24582     (flush _test-output-buffered-file)
24583 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24589     # check output
24590     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
24591     # . epilogue
24592     89/<- %esp 5/r32/ebp
24593     5d/pop-to-ebp
24594     c3/return
24595 
24596 test-add-reg-to-mem:
24597     #   add-to var1 var2/reg
24598     # =>
24599     #   01/add-to *(ebp+__) var2
24600     #
24601     # . prologue
24602     55/push-ebp
24603     89/<- %ebp 4/r32/esp
24604     # setup
24605     (clear-stream _test-output-stream)
24606     (clear-stream $_test-output-buffered-file->buffer)
24607 $test-add-reg-to-mem:initialize-type:
24608     # var type/ecx: (payload type-tree) = int
24609     68/push 0/imm32/right:null
24610     68/push 0/imm32/right:null
24611     68/push 0/imm32/left:unused
24612     68/push 1/imm32/value:int
24613     68/push 1/imm32/is-atom?:true
24614     68/push 0x11/imm32/alloc-id:fake:payload
24615     89/<- %ecx 4/r32/esp
24616 $test-add-reg-to-mem:initialize-var1:
24617     # var var1/ecx: (payload var)
24618     68/push 0/imm32/register
24619     68/push 0/imm32/register
24620     68/push 8/imm32/stack-offset
24621     68/push 1/imm32/block-depth
24622     51/push-ecx
24623     68/push 0x11/imm32/alloc-id:fake
24624     68/push 0/imm32/name
24625     68/push 0/imm32/name
24626     68/push 0x11/imm32/alloc-id:fake:payload
24627     89/<- %ecx 4/r32/esp
24628 $test-add-reg-to-mem:initialize-var1-name:
24629     # var1->name = "var1"
24630     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24631     (copy-array Heap "var1" %eax)
24632 $test-add-reg-to-mem:initialize-var2:
24633     # var var2/edx: (payload var)
24634     68/push 0/imm32/register
24635     68/push 0/imm32/register
24636     68/push 0/imm32/no-stack-offset
24637     68/push 1/imm32/block-depth
24638     ff 6/subop/push *(ecx+0x10)
24639     68/push 0x11/imm32/alloc-id:fake
24640     68/push 0/imm32/name
24641     68/push 0/imm32/name
24642     68/push 0x11/imm32/alloc-id:fake:payload
24643     89/<- %edx 4/r32/esp
24644 $test-add-reg-to-mem:initialize-var2-name:
24645     # var2->name = "var2"
24646     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
24647     (copy-array Heap "var2" %eax)
24648 $test-add-reg-to-mem:initialize-var2-register:
24649     # var2->register = "ecx"
24650     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
24651     (copy-array Heap "ecx" %eax)
24652 $test-add-reg-to-mem:initialize-inouts:
24653     # var inouts/esi: (payload stmt-var) = [var2]
24654     68/push 0/imm32/is-deref:false
24655     68/push 0/imm32/next
24656     68/push 0/imm32/next
24657     52/push-edx/var2
24658     68/push 0x11/imm32/alloc-id:fake
24659     68/push 0x11/imm32/alloc-id:fake:payload
24660     89/<- %esi 4/r32/esp
24661     # inouts = [var1, var2]
24662     68/push 0/imm32/is-deref:false
24663     56/push-esi/next
24664     68/push 0x11/imm32/alloc-id:fake
24665     51/push-ecx/var1
24666     68/push 0x11/imm32/alloc-id:fake
24667     68/push 0x11/imm32/alloc-id:fake:payload
24668     89/<- %esi 4/r32/esp
24669 $test-add-reg-to-mem:initialize-stmt:
24670     # var stmt/esi: (addr statement)
24671     68/push 0/imm32/next
24672     68/push 0/imm32/next
24673     68/push 0/imm32/outputs
24674     68/push 0/imm32/outputs
24675     56/push-esi/inouts
24676     68/push 0x11/imm32/alloc-id:fake
24677     68/push 0/imm32/operation
24678     68/push 0/imm32/operation
24679     68/push 1/imm32/tag:stmt1
24680     89/<- %esi 4/r32/esp
24681 $test-add-reg-to-mem:initialize-stmt-operation:
24682     # stmt->operation = "add-to"
24683     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24684     (copy-array Heap "add-to" %eax)
24685     # convert
24686     c7 0/subop/copy *Curr-block-depth 0/imm32
24687     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
24688     (flush _test-output-buffered-file)
24689 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24695     # check output
24696     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
24697     # . epilogue
24698     89/<- %esp 5/r32/ebp
24699     5d/pop-to-ebp
24700     c3/return
24701 
24702 test-add-mem-to-reg:
24703     #   var1/reg <- add var2
24704     # =>
24705     #   03/add *(ebp+__) var1
24706     #
24707     # . prologue
24708     55/push-ebp
24709     89/<- %ebp 4/r32/esp
24710     # setup
24711     (clear-stream _test-output-stream)
24712     (clear-stream $_test-output-buffered-file->buffer)
24713 $test-add-mem-to-reg:initialize-type:
24714     # var type/ecx: (payload type-tree) = int
24715     68/push 0/imm32/right:null
24716     68/push 0/imm32/right:null
24717     68/push 0/imm32/left:unused
24718     68/push 1/imm32/value:int
24719     68/push 1/imm32/is-atom?:true
24720     68/push 0x11/imm32/alloc-id:fake:payload
24721     89/<- %ecx 4/r32/esp
24722 $test-add-mem-to-reg:initialize-var:
24723     # var var1/ecx: (payload var)
24724     68/push 0/imm32/register
24725     68/push 0/imm32/register
24726     68/push 0/imm32/no-stack-offset
24727     68/push 1/imm32/block-depth
24728     51/push-ecx
24729     68/push 0x11/imm32/alloc-id:fake
24730     68/push 0/imm32/name
24731     68/push 0/imm32/name
24732     68/push 0x11/imm32/alloc-id:fake:payload
24733     89/<- %ecx 4/r32/esp
24734 $test-add-mem-to-reg:initialize-var-name:
24735     # var1->name = "foo"
24736     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24737     (copy-array Heap "var1" %eax)
24738 $test-add-mem-to-reg:initialize-var-register:
24739     # var1->register = "eax"
24740     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24741     (copy-array Heap "eax" %eax)
24742 $test-add-mem-to-reg:initialize-var2:
24743     # var var2/edx: (payload var)
24744     68/push 0/imm32/register
24745     68/push 0/imm32/register
24746     68/push 8/imm32/stack-offset
24747     68/push 1/imm32/block-depth
24748     ff 6/subop/push *(ecx+0x10)
24749     68/push 0x11/imm32/alloc-id:fake
24750     68/push 0/imm32/name
24751     68/push 0/imm32/name
24752     68/push 0x11/imm32/alloc-id:fake:payload
24753     89/<- %edx 4/r32/esp
24754 $test-add-mem-to-reg:initialize-var2-name:
24755     # var2->name = "var2"
24756     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
24757     (copy-array Heap "var2" %eax)
24758 $test-add-mem-to-reg:initialize-inouts:
24759     # var inouts/esi: (payload stmt-var) = [var2]
24760     68/push 0/imm32/is-deref:false
24761     68/push 0/imm32/next
24762     68/push 0/imm32/next
24763     52/push-edx/var2
24764     68/push 0x11/imm32/alloc-id:fake
24765     68/push 0x11/imm32/alloc-id:fake:payload
24766     89/<- %esi 4/r32/esp
24767 $test-add-mem-to-reg:initialize-outputs:
24768     # var outputs/edi: (payload stmt-var) = [var1]
24769     68/push 0/imm32/is-deref:false
24770     68/push 0/imm32/next
24771     68/push 0/imm32/next
24772     51/push-ecx/var1
24773     68/push 0x11/imm32/alloc-id:fake
24774     68/push 0x11/imm32/alloc-id:fake:payload
24775     89/<- %edi 4/r32/esp
24776 $test-add-mem-to-reg:initialize-stmt:
24777     # var stmt/esi: (addr statement)
24778     68/push 0/imm32/next
24779     68/push 0/imm32/next
24780     57/push-edi/outputs
24781     68/push 0x11/imm32/alloc-id:fake
24782     56/push-esi/inouts
24783     68/push 0x11/imm32/alloc-id:fake
24784     68/push 0/imm32/operation
24785     68/push 0/imm32/operation
24786     68/push 1/imm32/tag:stmt1
24787     89/<- %esi 4/r32/esp
24788 $test-add-mem-to-reg:initialize-stmt-operation:
24789     # stmt->operation = "add"
24790     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24791     (copy-array Heap "add" %eax)
24792     # convert
24793     c7 0/subop/copy *Curr-block-depth 0/imm32
24794     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
24795     (flush _test-output-buffered-file)
24796 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24802     # check output
24803     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
24804     # . epilogue
24805     89/<- %esp 5/r32/ebp
24806     5d/pop-to-ebp
24807     c3/return
24808 
24809 test-add-literal-to-eax:
24810     #   var1/eax <- add 0x34
24811     # =>
24812     #   05/add-to-eax 0x34/imm32
24813     #
24814     # . prologue
24815     55/push-ebp
24816     89/<- %ebp 4/r32/esp
24817     # setup
24818     (clear-stream _test-output-stream)
24819     (clear-stream $_test-output-buffered-file->buffer)
24820 $test-add-literal-to-eax:initialize-var-type:
24821     # var type/ecx: (payload type-tree) = int
24822     68/push 0/imm32/right:null
24823     68/push 0/imm32/right:null
24824     68/push 0/imm32/left:unused
24825     68/push 1/imm32/value:int
24826     68/push 1/imm32/is-atom?:true
24827     68/push 0x11/imm32/alloc-id:fake:payload
24828     89/<- %ecx 4/r32/esp
24829 $test-add-literal-to-eax:initialize-var:
24830     # var v/ecx: (payload var)
24831     68/push 0/imm32/register
24832     68/push 0/imm32/register
24833     68/push 0/imm32/no-stack-offset
24834     68/push 1/imm32/block-depth
24835     51/push-ecx
24836     68/push 0x11/imm32/alloc-id:fake
24837     68/push 0/imm32/name
24838     68/push 0/imm32/name
24839     68/push 0x11/imm32/alloc-id:fake:payload
24840     89/<- %ecx 4/r32/esp
24841 $test-add-literal-to-eax:initialize-var-name:
24842     # v->name = "v"
24843     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24844     (copy-array Heap "v" %eax)
24845 $test-add-literal-to-eax:initialize-var-register:
24846     # v->register = "eax"
24847     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24848     (copy-array Heap "eax" %eax)
24849 $test-add-literal-to-eax:initialize-literal-type:
24850     # var type/edx: (payload type-tree) = literal
24851     68/push 0/imm32/right:null
24852     68/push 0/imm32/right:null
24853     68/push 0/imm32/left:unused
24854     68/push 0/imm32/value:literal
24855     68/push 1/imm32/is-atom?:true
24856     68/push 0x11/imm32/alloc-id:fake:payload
24857     89/<- %edx 4/r32/esp
24858 $test-add-literal-to-eax:initialize-literal:
24859     # var l/edx: (payload var)
24860     68/push 0/imm32/register
24861     68/push 0/imm32/register
24862     68/push 0/imm32/no-stack-offset
24863     68/push 1/imm32/block-depth
24864     52/push-edx
24865     68/push 0x11/imm32/alloc-id:fake
24866     68/push 0/imm32/name
24867     68/push 0/imm32/name
24868     68/push 0x11/imm32/alloc-id:fake:payload
24869     89/<- %edx 4/r32/esp
24870 $test-add-literal-to-eax:initialize-literal-value:
24871     # l->name = "0x34"
24872     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
24873     (copy-array Heap "0x34" %eax)
24874 $test-add-literal-to-eax:initialize-inouts:
24875     # var inouts/esi: (payload stmt-var) = [l]
24876     68/push 0/imm32/is-deref:false
24877     68/push 0/imm32/next
24878     68/push 0/imm32/next
24879     52/push-edx/l
24880     68/push 0x11/imm32/alloc-id:fake
24881     68/push 0x11/imm32/alloc-id:fake:payload
24882     89/<- %esi 4/r32/esp
24883 $test-add-literal-to-eax:initialize-outputs:
24884     # var outputs/edi: (payload stmt-var) = [v]
24885     68/push 0/imm32/is-deref:false
24886     68/push 0/imm32/next
24887     68/push 0/imm32/next
24888     51/push-ecx/v
24889     68/push 0x11/imm32/alloc-id:fake
24890     68/push 0x11/imm32/alloc-id:fake:payload
24891     89/<- %edi 4/r32/esp
24892 $test-add-literal-to-eax:initialize-stmt:
24893     # var stmt/esi: (addr statement)
24894     68/push 0/imm32/next
24895     68/push 0/imm32/next
24896     57/push-edi/outputs
24897     68/push 0x11/imm32/alloc-id:fake
24898     56/push-esi/inouts
24899     68/push 0x11/imm32/alloc-id:fake
24900     68/push 0/imm32/operation
24901     68/push 0/imm32/operation
24902     68/push 1/imm32/tag:stmt1
24903     89/<- %esi 4/r32/esp
24904 $test-add-literal-to-eax:initialize-stmt-operation:
24905     # stmt->operation = "add"
24906     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
24907     (copy-array Heap "add" %eax)
24908     # convert
24909     c7 0/subop/copy *Curr-block-depth 0/imm32
24910     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
24911     (flush _test-output-buffered-file)
24912 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
24918     # check output
24919     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
24920     # . epilogue
24921     89/<- %esp 5/r32/ebp
24922     5d/pop-to-ebp
24923     c3/return
24924 
24925 test-add-literal-to-reg:
24926     #   var1/ecx <- add 0x34
24927     # =>
24928     #   81 0/subop/add %ecx 0x34/imm32
24929     #
24930     # . prologue
24931     55/push-ebp
24932     89/<- %ebp 4/r32/esp
24933     # setup
24934     (clear-stream _test-output-stream)
24935     (clear-stream $_test-output-buffered-file->buffer)
24936 $test-add-literal-to-reg:initialize-var-type:
24937     # var type/ecx: (payload type-tree) = int
24938     68/push 0/imm32/right:null
24939     68/push 0/imm32/right:null
24940     68/push 0/imm32/left:unused
24941     68/push 1/imm32/value:int
24942     68/push 1/imm32/is-atom?:true
24943     68/push 0x11/imm32/alloc-id:fake:payload
24944     89/<- %ecx 4/r32/esp
24945 $test-add-literal-to-reg:initialize-var:
24946     # var v/ecx: (payload var)
24947     68/push 0/imm32/register
24948     68/push 0/imm32/register
24949     68/push 0/imm32/no-stack-offset
24950     68/push 1/imm32/block-depth
24951     51/push-ecx
24952     68/push 0x11/imm32/alloc-id:fake
24953     68/push 0/imm32/name
24954     68/push 0/imm32/name
24955     68/push 0x11/imm32/alloc-id:fake:payload
24956     89/<- %ecx 4/r32/esp
24957 $test-add-literal-to-reg:initialize-var-name:
24958     # v->name = "v"
24959     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
24960     (copy-array Heap "v" %eax)
24961 $test-add-literal-to-reg:initialize-var-register:
24962     # v->register = "ecx"
24963     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
24964     (copy-array Heap "ecx" %eax)
24965 $test-add-literal-to-reg:initialize-literal-type:
24966     # var type/edx: (payload type-tree) = literal
24967     68/push 0/imm32/right:null
24968     68/push 0/imm32/right:null
24969     68/push 0/imm32/left:unused
24970     68/push 0/imm32/value:literal
24971     68/push 1/imm32/is-atom?:true
24972     68/push 0x11/imm32/alloc-id:fake:payload
24973     89/<- %edx 4/r32/esp
24974 $test-add-literal-to-reg:initialize-literal:
24975     # var l/edx: (payload var)
24976     68/push 0/imm32/register
24977     68/push 0/imm32/register
24978     68/push 0/imm32/no-stack-offset
24979     68/push 1/imm32/block-depth
24980     52/push-edx
24981     68/push 0x11/imm32/alloc-id:fake
24982     68/push 0/imm32/name
24983     68/push 0/imm32/name
24984     68/push 0x11/imm32/alloc-id:fake:payload
24985     89/<- %edx 4/r32/esp
24986 $test-add-literal-to-reg:initialize-literal-value:
24987     # l->name = "0x34"
24988     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
24989     (copy-array Heap "0x34" %eax)
24990 $test-add-literal-to-reg:initialize-inouts:
24991     # var inouts/esi: (payload stmt-var) = [l]
24992     68/push 0/imm32/is-deref:false
24993     68/push 0/imm32/next
24994     68/push 0/imm32/next
24995     52/push-edx/l
24996     68/push 0x11/imm32/alloc-id:fake
24997     68/push 0x11/imm32/alloc-id:fake:payload
24998     89/<- %esi 4/r32/esp
24999 $test-add-literal-to-reg:initialize-outputs:
25000     # var outputs/edi: (payload stmt-var) = [v]
25001     68/push 0/imm32/is-deref:false
25002     68/push 0/imm32/next
25003     68/push 0/imm32/next
25004     51/push-ecx/v
25005     68/push 0x11/imm32/alloc-id:fake
25006     68/push 0x11/imm32/alloc-id:fake:payload
25007     89/<- %edi 4/r32/esp
25008 $test-add-literal-to-reg:initialize-stmt:
25009     # var stmt/esi: (addr statement)
25010     68/push 0/imm32/next
25011     68/push 0/imm32/next
25012     57/push-edi/outputs
25013     68/push 0x11/imm32/alloc-id:fake
25014     56/push-esi/inouts
25015     68/push 0x11/imm32/alloc-id:fake
25016     68/push 0/imm32/operation
25017     68/push 0/imm32/operation
25018     68/push 1/imm32/tag:stmt1
25019     89/<- %esi 4/r32/esp
25020 $test-add-literal-to-reg:initialize-stmt-operation:
25021     # stmt->operation = "add"
25022     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25023     (copy-array Heap "add" %eax)
25024     # convert
25025     c7 0/subop/copy *Curr-block-depth 0/imm32
25026     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25027     (flush _test-output-buffered-file)
25028 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25034     # check output
25035     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
25036     # . epilogue
25037     89/<- %esp 5/r32/ebp
25038     5d/pop-to-ebp
25039     c3/return
25040 
25041 test-add-literal-to-mem:
25042     #   add-to var1, 0x34
25043     # =>
25044     #   81 0/subop/add %eax 0x34/imm32
25045     #
25046     # . prologue
25047     55/push-ebp
25048     89/<- %ebp 4/r32/esp
25049     # setup
25050     (clear-stream _test-output-stream)
25051     (clear-stream $_test-output-buffered-file->buffer)
25052 $test-add-literal-to-mem:initialize-type:
25053     # var type/ecx: (payload type-tree) = int
25054     68/push 0/imm32/right:null
25055     68/push 0/imm32/right:null
25056     68/push 0/imm32/left:unused
25057     68/push 1/imm32/value:int
25058     68/push 1/imm32/is-atom?:true
25059     68/push 0x11/imm32/alloc-id:fake:payload
25060     89/<- %ecx 4/r32/esp
25061 $test-add-literal-to-mem:initialize-var1:
25062     # var var1/ecx: (payload var)
25063     68/push 0/imm32/register
25064     68/push 0/imm32/register
25065     68/push 8/imm32/stack-offset
25066     68/push 1/imm32/block-depth
25067     51/push-ecx
25068     68/push 0x11/imm32/alloc-id:fake
25069     68/push 0/imm32/name
25070     68/push 0/imm32/name
25071     68/push 0x11/imm32/alloc-id:fake:payload
25072     89/<- %ecx 4/r32/esp
25073 $test-add-literal-to-mem:initialize-var1-name:
25074     # var1->name = "var1"
25075     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25076     (copy-array Heap "var1" %eax)
25077 $test-add-literal-to-mem:initialize-literal-type:
25078     # var type/edx: (payload type-tree) = literal
25079     68/push 0/imm32/right:null
25080     68/push 0/imm32/right:null
25081     68/push 0/imm32/left:unused
25082     68/push 0/imm32/value:literal
25083     68/push 1/imm32/is-atom?:true
25084     68/push 0x11/imm32/alloc-id:fake:payload
25085     89/<- %edx 4/r32/esp
25086 $test-add-literal-to-mem:initialize-literal:
25087     # var l/edx: (payload var)
25088     68/push 0/imm32/register
25089     68/push 0/imm32/register
25090     68/push 0/imm32/no-stack-offset
25091     68/push 1/imm32/block-depth
25092     52/push-edx
25093     68/push 0x11/imm32/alloc-id:fake
25094     68/push 0/imm32/name
25095     68/push 0/imm32/name
25096     68/push 0x11/imm32/alloc-id:fake:payload
25097     89/<- %edx 4/r32/esp
25098 $test-add-literal-to-mem:initialize-literal-value:
25099     # l->name = "0x34"
25100     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25101     (copy-array Heap "0x34" %eax)
25102 $test-add-literal-to-mem:initialize-inouts:
25103     # var inouts/esi: (payload stmt-var) = [l]
25104     68/push 0/imm32/is-deref:false
25105     68/push 0/imm32/next
25106     68/push 0/imm32/next
25107     52/push-edx/l
25108     68/push 0x11/imm32/alloc-id:fake
25109     68/push 0x11/imm32/alloc-id:fake:payload
25110     89/<- %esi 4/r32/esp
25111     # var inouts = (handle stmt-var) = [var1, var2]
25112     68/push 0/imm32/is-deref:false
25113     56/push-esi/next
25114     68/push 0x11/imm32/alloc-id:fake
25115     51/push-ecx/var1
25116     68/push 0x11/imm32/alloc-id:fake
25117     68/push 0x11/imm32/alloc-id:fake:payload
25118     89/<- %esi 4/r32/esp
25119 $test-add-literal-to-mem:initialize-stmt:
25120     # var stmt/esi: (addr statement)
25121     68/push 0/imm32/next
25122     68/push 0/imm32/next
25123     68/push 0/imm32/outputs
25124     68/push 0/imm32/outputs
25125     56/push-esi/inouts
25126     68/push 0x11/imm32/alloc-id:fake
25127     68/push 0/imm32/operation
25128     68/push 0/imm32/operation
25129     68/push 1/imm32/tag:stmt1
25130     89/<- %esi 4/r32/esp
25131 $test-add-literal-to-mem:initialize-stmt-operation:
25132     # stmt->operation = "add-to"
25133     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25134     (copy-array Heap "add-to" %eax)
25135     # convert
25136     c7 0/subop/copy *Curr-block-depth 0/imm32
25137     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25138     (flush _test-output-buffered-file)
25139 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25145     # check output
25146     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
25147     # . epilogue
25148     89/<- %esp 5/r32/ebp
25149     5d/pop-to-ebp
25150     c3/return
25151 
25152 test-shift-reg-by-literal:
25153     #   var1/ecx <- shift-left 2
25154     # =>
25155     #   c1/shift 4/subop/left %ecx 2/imm8
25156     #
25157     # . prologue
25158     55/push-ebp
25159     89/<- %ebp 4/r32/esp
25160     # setup
25161     (clear-stream _test-output-stream)
25162     (clear-stream $_test-output-buffered-file->buffer)
25163 $test-shift-reg-by-literal:initialize-var-type:
25164     # var type/ecx: (payload type-tree) = int
25165     68/push 0/imm32/right:null
25166     68/push 0/imm32/right:null
25167     68/push 0/imm32/left:unused
25168     68/push 1/imm32/value:int
25169     68/push 1/imm32/is-atom?:true
25170     68/push 0x11/imm32/alloc-id:fake:payload
25171     89/<- %ecx 4/r32/esp
25172 $test-shift-reg-by-literal:initialize-var:
25173     # var v/ecx: (payload var)
25174     68/push 0/imm32/register
25175     68/push 0/imm32/register
25176     68/push 0/imm32/no-stack-offset
25177     68/push 1/imm32/block-depth
25178     51/push-ecx
25179     68/push 0x11/imm32/alloc-id:fake
25180     68/push 0/imm32/name
25181     68/push 0/imm32/name
25182     68/push 0x11/imm32/alloc-id:fake:payload
25183     89/<- %ecx 4/r32/esp
25184 $test-shift-reg-by-literal:initialize-var-name:
25185     # v->name = "v"
25186     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25187     (copy-array Heap "v" %eax)
25188 $test-shift-reg-by-literal:initialize-var-register:
25189     # v->register = "ecx"
25190     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
25191     (copy-array Heap "ecx" %eax)
25192 $test-shift-reg-by-literal:initialize-literal-type:
25193     # var type/edx: (payload type-tree) = literal
25194     68/push 0/imm32/right:null
25195     68/push 0/imm32/right:null
25196     68/push 0/imm32/left:unused
25197     68/push 0/imm32/value:literal
25198     68/push 1/imm32/is-atom?:true
25199     68/push 0x11/imm32/alloc-id:fake:payload
25200     89/<- %edx 4/r32/esp
25201 $test-shift-reg-by-literal:initialize-literal:
25202     # var l/edx: (payload var)
25203     68/push 0/imm32/register
25204     68/push 0/imm32/register
25205     68/push 0/imm32/no-stack-offset
25206     68/push 1/imm32/block-depth
25207     52/push-edx
25208     68/push 0x11/imm32/alloc-id:fake
25209     68/push 0/imm32/name
25210     68/push 0/imm32/name
25211     68/push 0x11/imm32/alloc-id:fake:payload
25212     89/<- %edx 4/r32/esp
25213 $test-shift-reg-by-literal:initialize-literal-value:
25214     # l->name = "2"
25215     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25216     (copy-array Heap "2" %eax)
25217 $test-shift-reg-by-literal:initialize-inouts:
25218     # var inouts/esi: (payload stmt-var) = [l]
25219     68/push 0/imm32/is-deref:false
25220     68/push 0/imm32/next
25221     68/push 0/imm32/next
25222     52/push-edx/l
25223     68/push 0x11/imm32/alloc-id:fake
25224     68/push 0x11/imm32/alloc-id:fake:payload
25225     89/<- %esi 4/r32/esp
25226 $test-shift-reg-by-literal:initialize-outputs:
25227     # var outputs/edi: (payload stmt-var) = [v]
25228     68/push 0/imm32/is-deref:false
25229     68/push 0/imm32/next
25230     68/push 0/imm32/next
25231     51/push-ecx/v
25232     68/push 0x11/imm32/alloc-id:fake
25233     68/push 0x11/imm32/alloc-id:fake:payload
25234     89/<- %edi 4/r32/esp
25235 $test-shift-reg-by-literal:initialize-stmt:
25236     # var stmt/esi: (addr statement)
25237     68/push 0/imm32/next
25238     68/push 0/imm32/next
25239     57/push-edi/outputs
25240     68/push 0x11/imm32/alloc-id:fake
25241     56/push-esi/inouts
25242     68/push 0x11/imm32/alloc-id:fake
25243     68/push 0/imm32/operation
25244     68/push 0/imm32/operation
25245     68/push 1/imm32/tag:stmt1
25246     89/<- %esi 4/r32/esp
25247 $test-shift-reg-by-literal:initialize-stmt-operation:
25248     # stmt->operation = "shift-left"
25249     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25250     (copy-array Heap "shift-left" %eax)
25251     # convert
25252     c7 0/subop/copy *Curr-block-depth 0/imm32
25253     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25254     (flush _test-output-buffered-file)
25255 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25261     # check output
25262     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
25263     # . epilogue
25264     89/<- %esp 5/r32/ebp
25265     5d/pop-to-ebp
25266     c3/return
25267 
25268 test-shift-mem-by-literal:
25269     #   shift-left var 3
25270     # =>
25271     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
25272     #
25273     # . prologue
25274     55/push-ebp
25275     89/<- %ebp 4/r32/esp
25276     # setup
25277     (clear-stream _test-output-stream)
25278     (clear-stream $_test-output-buffered-file->buffer)
25279 $test-shift-mem-by-literal:initialize-type:
25280     # var type/ecx: (payload type-tree) = int
25281     68/push 0/imm32/right:null
25282     68/push 0/imm32/right:null
25283     68/push 0/imm32/left:unused
25284     68/push 1/imm32/value:int
25285     68/push 1/imm32/is-atom?:true
25286     68/push 0x11/imm32/alloc-id:fake:payload
25287     89/<- %ecx 4/r32/esp
25288 $test-shift-mem-by-literal:initialize-var1:
25289     # var var1/ecx: (payload var)
25290     68/push 0/imm32/register
25291     68/push 0/imm32/register
25292     68/push 8/imm32/stack-offset
25293     68/push 1/imm32/block-depth
25294     51/push-ecx
25295     68/push 0x11/imm32/alloc-id:fake
25296     68/push 0/imm32/name
25297     68/push 0/imm32/name
25298     68/push 0x11/imm32/alloc-id:fake:payload
25299     89/<- %ecx 4/r32/esp
25300 $test-shift-mem-by-literal:initialize-var1-name:
25301     # var1->name = "var1"
25302     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25303     (copy-array Heap "var1" %eax)
25304 $test-shift-mem-by-literal:initialize-literal-type:
25305     # var type/edx: (payload type-tree) = literal
25306     68/push 0/imm32/right:null
25307     68/push 0/imm32/right:null
25308     68/push 0/imm32/left:unused
25309     68/push 0/imm32/value:literal
25310     68/push 1/imm32/is-atom?:true
25311     68/push 0x11/imm32/alloc-id:fake:payload
25312     89/<- %edx 4/r32/esp
25313 $test-shift-mem-by-literal:initialize-literal:
25314     # var l/edx: (payload var)
25315     68/push 0/imm32/register
25316     68/push 0/imm32/register
25317     68/push 0/imm32/no-stack-offset
25318     68/push 1/imm32/block-depth
25319     52/push-edx
25320     68/push 0x11/imm32/alloc-id:fake
25321     68/push 0/imm32/name
25322     68/push 0/imm32/name
25323     68/push 0x11/imm32/alloc-id:fake:payload
25324     89/<- %edx 4/r32/esp
25325 $test-shift-mem-by-literal:initialize-literal-value:
25326     # l->name = "3"
25327     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25328     (copy-array Heap "3" %eax)
25329 $test-shift-mem-by-literal:initialize-inouts:
25330     # var inouts/esi: (payload stmt-var) = [l]
25331     68/push 0/imm32/is-deref:false
25332     68/push 0/imm32/next
25333     68/push 0/imm32/next
25334     52/push-edx/l
25335     68/push 0x11/imm32/alloc-id:fake
25336     68/push 0x11/imm32/alloc-id:fake:payload
25337     89/<- %esi 4/r32/esp
25338     # var inouts = (handle stmt-var) = [var1, var2]
25339     68/push 0/imm32/is-deref:false
25340     56/push-esi/next
25341     68/push 0x11/imm32/alloc-id:fake
25342     51/push-ecx/var1
25343     68/push 0x11/imm32/alloc-id:fake
25344     68/push 0x11/imm32/alloc-id:fake:payload
25345     89/<- %esi 4/r32/esp
25346 $test-shift-mem-by-literal:initialize-stmt:
25347     # var stmt/esi: (addr statement)
25348     68/push 0/imm32/next
25349     68/push 0/imm32/next
25350     68/push 0/imm32/outputs
25351     68/push 0/imm32/outputs
25352     56/push-esi/inouts
25353     68/push 0x11/imm32/alloc-id:fake
25354     68/push 0/imm32/operation
25355     68/push 0/imm32/operation
25356     68/push 1/imm32/tag:stmt1
25357     89/<- %esi 4/r32/esp
25358 $test-shift-mem-by-literal:initialize-stmt-operation:
25359     # stmt->operation = "shift-left"
25360     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25361     (copy-array Heap "shift-left" %eax)
25362     # convert
25363     c7 0/subop/copy *Curr-block-depth 0/imm32
25364     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25365     (flush _test-output-buffered-file)
25366 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25372     # check output
25373     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
25374     # . epilogue
25375     89/<- %esp 5/r32/ebp
25376     5d/pop-to-ebp
25377     c3/return
25378 
25379 test-compare-reg-with-reg:
25380     #   compare var1/ecx, var2/eax
25381     # =>
25382     #   39/compare %ecx 0/r32/eax
25383     #
25384     # . prologue
25385     55/push-ebp
25386     89/<- %ebp 4/r32/esp
25387     # setup
25388     (clear-stream _test-output-stream)
25389     (clear-stream $_test-output-buffered-file->buffer)
25390 $test-compare-reg-with-reg:initialize-type:
25391     # var type/ecx: (payload type-tree) = int
25392     68/push 0/imm32/right:null
25393     68/push 0/imm32/right:null
25394     68/push 0/imm32/left:unused
25395     68/push 1/imm32/value:int
25396     68/push 1/imm32/is-atom?:true
25397     68/push 0x11/imm32/alloc-id:fake:payload
25398     89/<- %ecx 4/r32/esp
25399 $test-compare-reg-with-reg:initialize-var1:
25400     # var var1/ecx: (payload var)
25401     68/push 0/imm32/register
25402     68/push 0/imm32/register
25403     68/push 0/imm32/no-stack-offset
25404     68/push 1/imm32/block-depth
25405     51/push-ecx
25406     68/push 0x11/imm32/alloc-id:fake
25407     68/push 0/imm32/name
25408     68/push 0/imm32/name
25409     68/push 0x11/imm32/alloc-id:fake:payload
25410     89/<- %ecx 4/r32/esp
25411 $test-compare-reg-with-reg:initialize-var1-name:
25412     # var1->name = "var1"
25413     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25414     (copy-array Heap "var1" %eax)
25415 $test-compare-reg-with-reg:initialize-var1-register:
25416     # var1->register = "ecx"
25417     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
25418     (copy-array Heap "ecx" %eax)
25419 $test-compare-reg-with-reg:initialize-var2:
25420     # var var2/edx: (payload var)
25421     68/push 0/imm32/register
25422     68/push 0/imm32/register
25423     68/push 0/imm32/no-stack-offset
25424     68/push 1/imm32/block-depth
25425     ff 6/subop/push *(ecx+0x10)
25426     68/push 0x11/imm32/alloc-id:fake
25427     68/push 0/imm32/name
25428     68/push 0/imm32/name
25429     68/push 0x11/imm32/alloc-id:fake:payload
25430     89/<- %edx 4/r32/esp
25431 $test-compare-reg-with-reg:initialize-var2-name:
25432     # var2->name = "var2"
25433     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25434     (copy-array Heap "var2" %eax)
25435 $test-compare-reg-with-reg:initialize-var2-register:
25436     # var2->register = "eax"
25437     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
25438     (copy-array Heap "eax" %eax)
25439 $test-compare-reg-with-reg:initialize-inouts:
25440     # var inouts/esi: (payload stmt-var) = [var2]
25441     68/push 0/imm32/is-deref:false
25442     68/push 0/imm32/next
25443     68/push 0/imm32/next
25444     52/push-edx/var2
25445     68/push 0x11/imm32/alloc-id:fake
25446     68/push 0x11/imm32/alloc-id:fake:payload
25447     89/<- %esi 4/r32/esp
25448     # inouts = [var1, var2]
25449     68/push 0/imm32/is-deref:false
25450     56/push-esi/next
25451     68/push 0x11/imm32/alloc-id:fake
25452     51/push-ecx/var1
25453     68/push 0x11/imm32/alloc-id:fake
25454     68/push 0x11/imm32/alloc-id:fake:payload
25455     89/<- %esi 4/r32/esp
25456 $test-compare-reg-with-reg:initialize-stmt:
25457     # var stmt/esi: (addr statement)
25458     68/push 0/imm32/next
25459     68/push 0/imm32/next
25460     68/push 0/imm32/outputs
25461     68/push 0/imm32/outputs
25462     56/push-esi/inouts
25463     68/push 0x11/imm32/alloc-id:fake
25464     68/push 0/imm32/operation
25465     68/push 0/imm32/operation
25466     68/push 1/imm32/tag:stmt1
25467     89/<- %esi 4/r32/esp
25468 $test-compare-reg-with-reg:initialize-stmt-operation:
25469     # stmt->operation = "compare"
25470     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25471     (copy-array Heap "compare" %eax)
25472     # convert
25473     c7 0/subop/copy *Curr-block-depth 0/imm32
25474     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25475     (flush _test-output-buffered-file)
25476 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25482     # check output
25483     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
25484     # . epilogue
25485     89/<- %esp 5/r32/ebp
25486     5d/pop-to-ebp
25487     c3/return
25488 
25489 test-compare-mem-with-reg:
25490     #   compare var1, var2/eax
25491     # =>
25492     #   39/compare *(ebp+___) 0/r32/eax
25493     #
25494     # . prologue
25495     55/push-ebp
25496     89/<- %ebp 4/r32/esp
25497     # setup
25498     (clear-stream _test-output-stream)
25499     (clear-stream $_test-output-buffered-file->buffer)
25500 $test-compare-mem-with-reg:initialize-type:
25501     # var type/ecx: (payload type-tree) = int
25502     68/push 0/imm32/right:null
25503     68/push 0/imm32/right:null
25504     68/push 0/imm32/left:unused
25505     68/push 1/imm32/value:int
25506     68/push 1/imm32/is-atom?:true
25507     68/push 0x11/imm32/alloc-id:fake:payload
25508     89/<- %ecx 4/r32/esp
25509 $test-compare-mem-with-reg:initialize-var1:
25510     # var var1/ecx: (payload var)
25511     68/push 0/imm32/register
25512     68/push 0/imm32/register
25513     68/push 8/imm32/stack-offset
25514     68/push 1/imm32/block-depth
25515     51/push-ecx
25516     68/push 0x11/imm32/alloc-id:fake
25517     68/push 0/imm32/name
25518     68/push 0/imm32/name
25519     68/push 0x11/imm32/alloc-id:fake:payload
25520     89/<- %ecx 4/r32/esp
25521 $test-compare-mem-with-reg:initialize-var1-name:
25522     # var1->name = "var1"
25523     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25524     (copy-array Heap "var1" %eax)
25525 $test-compare-mem-with-reg:initialize-var2:
25526     # var var2/edx: (payload var)
25527     68/push 0/imm32/register
25528     68/push 0/imm32/register
25529     68/push 0/imm32/no-stack-offset
25530     68/push 1/imm32/block-depth
25531     ff 6/subop/push *(ecx+0x10)
25532     68/push 0x11/imm32/alloc-id:fake
25533     68/push 0/imm32/name
25534     68/push 0/imm32/name
25535     68/push 0x11/imm32/alloc-id:fake:payload
25536     89/<- %edx 4/r32/esp
25537 $test-compare-mem-with-reg:initialize-var2-name:
25538     # var2->name = "var2"
25539     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25540     (copy-array Heap "var2" %eax)
25541 $test-compare-mem-with-reg:initialize-var2-register:
25542     # var2->register = "eax"
25543     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
25544     (copy-array Heap "eax" %eax)
25545 $test-compare-mem-with-reg:initialize-inouts:
25546     # var inouts/esi: (payload stmt-var) = [var2]
25547     68/push 0/imm32/is-deref:false
25548     68/push 0/imm32/next
25549     68/push 0/imm32/next
25550     52/push-edx/var2
25551     68/push 0x11/imm32/alloc-id:fake
25552     68/push 0x11/imm32/alloc-id:fake:payload
25553     89/<- %esi 4/r32/esp
25554     # inouts = [var1, var2]
25555     68/push 0/imm32/is-deref:false
25556     56/push-esi/next
25557     68/push 0x11/imm32/alloc-id:fake
25558     51/push-ecx/var1
25559     68/push 0x11/imm32/alloc-id:fake
25560     68/push 0x11/imm32/alloc-id:fake:payload
25561     89/<- %esi 4/r32/esp
25562 $test-compare-mem-with-reg:initialize-stmt:
25563     # var stmt/esi: (addr statement)
25564     68/push 0/imm32/next
25565     68/push 0/imm32/next
25566     68/push 0/imm32/outputs
25567     68/push 0/imm32/outputs
25568     56/push-esi/inouts
25569     68/push 0x11/imm32/alloc-id:fake
25570     68/push 0/imm32/operation
25571     68/push 0/imm32/operation
25572     68/push 1/imm32/tag:stmt1
25573     89/<- %esi 4/r32/esp
25574 $test-compare-mem-with-reg:initialize-stmt-operation:
25575     # stmt->operation = "compare"
25576     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25577     (copy-array Heap "compare" %eax)
25578     # convert
25579     c7 0/subop/copy *Curr-block-depth 0/imm32
25580     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25581     (flush _test-output-buffered-file)
25582 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25588     # check output
25589     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
25590     # . epilogue
25591     89/<- %esp 5/r32/ebp
25592     5d/pop-to-ebp
25593     c3/return
25594 
25595 test-compare-reg-with-mem:
25596     #   compare var1/eax, var2
25597     # =>
25598     #   3b/compare<- *(ebp+___) 0/r32/eax
25599     #
25600     # . prologue
25601     55/push-ebp
25602     89/<- %ebp 4/r32/esp
25603     # setup
25604     (clear-stream _test-output-stream)
25605     (clear-stream $_test-output-buffered-file->buffer)
25606 $test-compare-reg-with-mem:initialize-type:
25607     # var type/ecx: (payload type-tree) = int
25608     68/push 0/imm32/right:null
25609     68/push 0/imm32/right:null
25610     68/push 0/imm32/left:unused
25611     68/push 1/imm32/value:int
25612     68/push 1/imm32/is-atom?:true
25613     68/push 0x11/imm32/alloc-id:fake:payload
25614     89/<- %ecx 4/r32/esp
25615 $test-compare-reg-with-mem:initialize-var1:
25616     # var var1/ecx: (payload var)
25617     68/push 0/imm32/register
25618     68/push 0/imm32/register
25619     68/push 0/imm32/no-stack-offset
25620     68/push 1/imm32/block-depth
25621     51/push-ecx
25622     68/push 0x11/imm32/alloc-id:fake
25623     68/push 0/imm32/name
25624     68/push 0/imm32/name
25625     68/push 0x11/imm32/alloc-id:fake:payload
25626     89/<- %ecx 4/r32/esp
25627 $test-compare-reg-with-mem:initialize-var1-name:
25628     # var1->name = "var1"
25629     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25630     (copy-array Heap "var1" %eax)
25631 $test-compare-reg-with-mem:initialize-var1-register:
25632     # var1->register = "eax"
25633     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
25634     (copy-array Heap "eax" %eax)
25635 $test-compare-reg-with-mem:initialize-var2:
25636     # var var2/edx: (payload var)
25637     68/push 0/imm32/register
25638     68/push 0/imm32/register
25639     68/push 8/imm32/stack-offset
25640     68/push 1/imm32/block-depth
25641     ff 6/subop/push *(ecx+0x10)
25642     68/push 0x11/imm32/alloc-id:fake
25643     68/push 0/imm32/name
25644     68/push 0/imm32/name
25645     68/push 0x11/imm32/alloc-id:fake:payload
25646     89/<- %edx 4/r32/esp
25647 $test-compare-reg-with-mem:initialize-var2-name:
25648     # var2->name = "var2"
25649     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25650     (copy-array Heap "var2" %eax)
25651 $test-compare-reg-with-mem:initialize-inouts:
25652     # var inouts/esi: (payload stmt-var) = [var2]
25653     68/push 0/imm32/is-deref:false
25654     68/push 0/imm32/next
25655     68/push 0/imm32/next
25656     52/push-edx/var2
25657     68/push 0x11/imm32/alloc-id:fake
25658     68/push 0x11/imm32/alloc-id:fake:payload
25659     89/<- %esi 4/r32/esp
25660     # inouts = [var1, var2]
25661     68/push 0/imm32/is-deref:false
25662     56/push-esi/next
25663     68/push 0x11/imm32/alloc-id:fake
25664     51/push-ecx/var1
25665     68/push 0x11/imm32/alloc-id:fake
25666     68/push 0x11/imm32/alloc-id:fake:payload
25667     89/<- %esi 4/r32/esp
25668 $test-compare-reg-with-mem:initialize-stmt:
25669     # var stmt/esi: (addr statement)
25670     68/push 0/imm32/next
25671     68/push 0/imm32/next
25672     68/push 0/imm32/outputs
25673     68/push 0/imm32/outputs
25674     56/push-esi/inouts
25675     68/push 0x11/imm32/alloc-id:fake
25676     68/push 0/imm32/operation
25677     68/push 0/imm32/operation
25678     68/push 1/imm32/tag:stmt1
25679     89/<- %esi 4/r32/esp
25680 $test-compare-reg-with-mem:initialize-stmt-operation:
25681     # stmt->operation = "compare"
25682     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25683     (copy-array Heap "compare" %eax)
25684     # convert
25685     c7 0/subop/copy *Curr-block-depth 0/imm32
25686     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25687     (flush _test-output-buffered-file)
25688 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25694     # check output
25695     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
25696     # . epilogue
25697     89/<- %esp 5/r32/ebp
25698     5d/pop-to-ebp
25699     c3/return
25700 
25701 test-compare-mem-with-literal:
25702     #   compare var1, 0x34
25703     # =>
25704     #   81 7/subop/compare *(ebp+___) 0x34/imm32
25705     #
25706     # . prologue
25707     55/push-ebp
25708     89/<- %ebp 4/r32/esp
25709     # setup
25710     (clear-stream _test-output-stream)
25711     (clear-stream $_test-output-buffered-file->buffer)
25712 $test-compare-mem-with-literal:initialize-type:
25713     # var type/ecx: (payload type-tree) = int
25714     68/push 0/imm32/right:null
25715     68/push 0/imm32/right:null
25716     68/push 0/imm32/left:unused
25717     68/push 1/imm32/value:int
25718     68/push 1/imm32/is-atom?:true
25719     68/push 0x11/imm32/alloc-id:fake:payload
25720     89/<- %ecx 4/r32/esp
25721 $test-compare-mem-with-literal:initialize-var1:
25722     # var var1/ecx: (payload var)
25723     68/push 0/imm32/register
25724     68/push 0/imm32/register
25725     68/push 8/imm32/stack-offset
25726     68/push 1/imm32/block-depth
25727     51/push-ecx
25728     68/push 0x11/imm32/alloc-id:fake
25729     68/push 0/imm32/name
25730     68/push 0/imm32/name
25731     68/push 0x11/imm32/alloc-id:fake:payload
25732     89/<- %ecx 4/r32/esp
25733 $test-compare-mem-with-literal:initialize-var1-name:
25734     # var1->name = "var1"
25735     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25736     (copy-array Heap "var1" %eax)
25737 $test-compare-mem-with-literal:initialize-literal-type:
25738     # var type/edx: (payload type-tree) = literal
25739     68/push 0/imm32/right:null
25740     68/push 0/imm32/right:null
25741     68/push 0/imm32/left:unused
25742     68/push 0/imm32/value:literal
25743     68/push 1/imm32/is-atom?:true
25744     68/push 0x11/imm32/alloc-id:fake:payload
25745     89/<- %edx 4/r32/esp
25746 $test-compare-mem-with-literal:initialize-literal:
25747     # var l/edx: (payload var)
25748     68/push 0/imm32/register
25749     68/push 0/imm32/register
25750     68/push 0/imm32/no-stack-offset
25751     68/push 1/imm32/block-depth
25752     52/push-edx
25753     68/push 0x11/imm32/alloc-id:fake
25754     68/push 0/imm32/name
25755     68/push 0/imm32/name
25756     68/push 0x11/imm32/alloc-id:fake:payload
25757     89/<- %edx 4/r32/esp
25758 $test-compare-mem-with-literal:initialize-literal-value:
25759     # l->name = "0x34"
25760     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25761     (copy-array Heap "0x34" %eax)
25762 $test-compare-mem-with-literal:initialize-inouts:
25763     # var inouts/esi: (payload stmt-var) = [l]
25764     68/push 0/imm32/is-deref:false
25765     68/push 0/imm32/next
25766     68/push 0/imm32/next
25767     52/push-edx/l
25768     68/push 0x11/imm32/alloc-id:fake
25769     68/push 0x11/imm32/alloc-id:fake:payload
25770     89/<- %esi 4/r32/esp
25771     # var inouts = (handle stmt-var) = [var1, var2]
25772     68/push 0/imm32/is-deref:false
25773     56/push-esi/next
25774     68/push 0x11/imm32/alloc-id:fake
25775     51/push-ecx/var1
25776     68/push 0x11/imm32/alloc-id:fake
25777     68/push 0x11/imm32/alloc-id:fake:payload
25778     89/<- %esi 4/r32/esp
25779 $test-compare-mem-with-literal:initialize-stmt:
25780     # var stmt/esi: (addr statement)
25781     68/push 0/imm32/next
25782     68/push 0/imm32/next
25783     68/push 0/imm32/outputs
25784     68/push 0/imm32/outputs
25785     56/push-esi/inouts
25786     68/push 0x11/imm32/alloc-id:fake
25787     68/push 0/imm32/operation
25788     68/push 0/imm32/operation
25789     68/push 1/imm32/tag:stmt1
25790     89/<- %esi 4/r32/esp
25791 $test-compare-mem-with-literal:initialize-stmt-operation:
25792     # stmt->operation = "compare"
25793     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25794     (copy-array Heap "compare" %eax)
25795     # convert
25796     c7 0/subop/copy *Curr-block-depth 0/imm32
25797     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25798     (flush _test-output-buffered-file)
25799 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25805     # check output
25806     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
25807     # . epilogue
25808     89/<- %esp 5/r32/ebp
25809     5d/pop-to-ebp
25810     c3/return
25811 
25812 test-compare-eax-with-literal:
25813     #   compare var1/eax 0x34
25814     # =>
25815     #   3d/compare-eax-with 0x34/imm32
25816     #
25817     # . prologue
25818     55/push-ebp
25819     89/<- %ebp 4/r32/esp
25820     # setup
25821     (clear-stream _test-output-stream)
25822     (clear-stream $_test-output-buffered-file->buffer)
25823 $test-compare-eax-with-literal:initialize-type:
25824     # var type/ecx: (payload type-tree) = int
25825     68/push 0/imm32/right:null
25826     68/push 0/imm32/right:null
25827     68/push 0/imm32/left:unused
25828     68/push 1/imm32/value:int
25829     68/push 1/imm32/is-atom?:true
25830     68/push 0x11/imm32/alloc-id:fake:payload
25831     89/<- %ecx 4/r32/esp
25832 $test-compare-eax-with-literal:initialize-var1:
25833     # var var1/ecx: (payload var)
25834     68/push 0/imm32/register
25835     68/push 0/imm32/register
25836     68/push 0/imm32/no-stack-offset
25837     68/push 1/imm32/block-depth
25838     51/push-ecx
25839     68/push 0x11/imm32/alloc-id:fake
25840     68/push 0/imm32/name
25841     68/push 0/imm32/name
25842     68/push 0x11/imm32/alloc-id:fake:payload
25843     89/<- %ecx 4/r32/esp
25844 $test-compare-eax-with-literal:initialize-var1-name:
25845     # var1->name = "var1"
25846     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25847     (copy-array Heap "var1" %eax)
25848 $test-compare-eax-with-literal:initialize-var1-register:
25849     # v->register = "eax"
25850     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
25851     (copy-array Heap "eax" %eax)
25852 $test-compare-eax-with-literal:initialize-literal-type:
25853     # var type/edx: (payload type-tree) = literal
25854     68/push 0/imm32/right:null
25855     68/push 0/imm32/right:null
25856     68/push 0/imm32/left:unused
25857     68/push 0/imm32/value:literal
25858     68/push 1/imm32/is-atom?:true
25859     68/push 0x11/imm32/alloc-id:fake:payload
25860     89/<- %edx 4/r32/esp
25861 $test-compare-eax-with-literal:initialize-literal:
25862     # var l/edx: (payload var)
25863     68/push 0/imm32/register
25864     68/push 0/imm32/register
25865     68/push 0/imm32/no-stack-offset
25866     68/push 1/imm32/block-depth
25867     52/push-edx
25868     68/push 0x11/imm32/alloc-id:fake
25869     68/push 0/imm32/name
25870     68/push 0/imm32/name
25871     68/push 0x11/imm32/alloc-id:fake:payload
25872     89/<- %edx 4/r32/esp
25873 $test-compare-eax-with-literal:initialize-literal-value:
25874     # l->name = "0x34"
25875     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25876     (copy-array Heap "0x34" %eax)
25877 $test-compare-eax-with-literal:initialize-inouts:
25878     # var inouts/esi: (payload stmt-var) = [l]
25879     68/push 0/imm32/is-deref:false
25880     68/push 0/imm32/next
25881     68/push 0/imm32/next
25882     52/push-edx/l
25883     68/push 0x11/imm32/alloc-id:fake
25884     68/push 0x11/imm32/alloc-id:fake:payload
25885     89/<- %esi 4/r32/esp
25886     # var inouts = (handle stmt-var) = [var1, var2]
25887     68/push 0/imm32/is-deref:false
25888     56/push-esi/next
25889     68/push 0x11/imm32/alloc-id:fake
25890     51/push-ecx/var1
25891     68/push 0x11/imm32/alloc-id:fake
25892     68/push 0x11/imm32/alloc-id:fake:payload
25893     89/<- %esi 4/r32/esp
25894 $test-compare-eax-with-literal:initialize-stmt:
25895     # var stmt/esi: (addr statement)
25896     68/push 0/imm32/next
25897     68/push 0/imm32/next
25898     68/push 0/imm32/outputs
25899     68/push 0/imm32/outputs
25900     56/push-esi/inouts
25901     68/push 0x11/imm32/alloc-id:fake
25902     68/push 0/imm32/operation
25903     68/push 0/imm32/operation
25904     68/push 1/imm32/tag:stmt1
25905     89/<- %esi 4/r32/esp
25906 $test-compare-eax-with-literal:initialize-stmt-operation:
25907     # stmt->operation = "compare"
25908     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
25909     (copy-array Heap "compare" %eax)
25910     # convert
25911     c7 0/subop/copy *Curr-block-depth 0/imm32
25912     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
25913     (flush _test-output-buffered-file)
25914 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
25920     # check output
25921     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
25922     # . epilogue
25923     89/<- %esp 5/r32/ebp
25924     5d/pop-to-ebp
25925     c3/return
25926 
25927 test-compare-reg-with-literal:
25928     #   compare var1/ecx 0x34
25929     # =>
25930     #   81 7/subop/compare %ecx 0x34/imm32
25931     #
25932     # . prologue
25933     55/push-ebp
25934     89/<- %ebp 4/r32/esp
25935     # setup
25936     (clear-stream _test-output-stream)
25937     (clear-stream $_test-output-buffered-file->buffer)
25938 $test-compare-reg-with-literal:initialize-type:
25939     # var type/ecx: (payload type-tree) = int
25940     68/push 0/imm32/right:null
25941     68/push 0/imm32/right:null
25942     68/push 0/imm32/left:unused
25943     68/push 1/imm32/value:int
25944     68/push 1/imm32/is-atom?:true
25945     68/push 0x11/imm32/alloc-id:fake:payload
25946     89/<- %ecx 4/r32/esp
25947 $test-compare-reg-with-literal:initialize-var1:
25948     # var var1/ecx: (payload var)
25949     68/push 0/imm32/register
25950     68/push 0/imm32/register
25951     68/push 0/imm32/no-stack-offset
25952     68/push 1/imm32/block-depth
25953     51/push-ecx
25954     68/push 0x11/imm32/alloc-id:fake
25955     68/push 0/imm32/name
25956     68/push 0/imm32/name
25957     68/push 0x11/imm32/alloc-id:fake:payload
25958     89/<- %ecx 4/r32/esp
25959 $test-compare-reg-with-literal:initialize-var1-name:
25960     # var1->name = "var1"
25961     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
25962     (copy-array Heap "var1" %eax)
25963 $test-compare-reg-with-literal:initialize-var1-register:
25964     # v->register = "ecx"
25965     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
25966     (copy-array Heap "ecx" %eax)
25967 $test-compare-reg-with-literal:initialize-literal-type:
25968     # var type/edx: (payload type-tree) = literal
25969     68/push 0/imm32/right:null
25970     68/push 0/imm32/right:null
25971     68/push 0/imm32/left:unused
25972     68/push 0/imm32/value:literal
25973     68/push 1/imm32/is-atom?:true
25974     68/push 0x11/imm32/alloc-id:fake:payload
25975     89/<- %edx 4/r32/esp
25976 $test-compare-reg-with-literal:initialize-literal:
25977     # var l/edx: (payload var)
25978     68/push 0/imm32/register
25979     68/push 0/imm32/register
25980     68/push 0/imm32/no-stack-offset
25981     68/push 1/imm32/block-depth
25982     52/push-edx
25983     68/push 0x11/imm32/alloc-id:fake
25984     68/push 0/imm32/name
25985     68/push 0/imm32/name
25986     68/push 0x11/imm32/alloc-id:fake:payload
25987     89/<- %edx 4/r32/esp
25988 $test-compare-reg-with-literal:initialize-literal-value:
25989     # l->name = "0x34"
25990     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
25991     (copy-array Heap "0x34" %eax)
25992 $test-compare-reg-with-literal:initialize-inouts:
25993     # var inouts/esi: (payload stmt-var) = [l]
25994     68/push 0/imm32/is-deref:false
25995     68/push 0/imm32/next
25996     68/push 0/imm32/next
25997     52/push-edx/l
25998     68/push 0x11/imm32/alloc-id:fake
25999     68/push 0x11/imm32/alloc-id:fake:payload
26000     89/<- %esi 4/r32/esp
26001     # var inouts = (handle stmt-var) = [var1, var2]
26002     68/push 0/imm32/is-deref:false
26003     56/push-esi/next
26004     68/push 0x11/imm32/alloc-id:fake
26005     51/push-ecx/var1
26006     68/push 0x11/imm32/alloc-id:fake
26007     68/push 0x11/imm32/alloc-id:fake:payload
26008     89/<- %esi 4/r32/esp
26009 $test-compare-reg-with-literal:initialize-stmt:
26010     # var stmt/esi: (addr statement)
26011     68/push 0/imm32/next
26012     68/push 0/imm32/next
26013     68/push 0/imm32/outputs
26014     68/push 0/imm32/outputs
26015     56/push-esi/inouts
26016     68/push 0x11/imm32/alloc-id:fake
26017     68/push 0/imm32/operation
26018     68/push 0/imm32/operation
26019     68/push 1/imm32/tag:stmt1
26020     89/<- %esi 4/r32/esp
26021 $test-compare-reg-with-literal:initialize-stmt-operation:
26022     # stmt->operation = "compare"
26023     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
26024     (copy-array Heap "compare" %eax)
26025     # convert
26026     c7 0/subop/copy *Curr-block-depth 0/imm32
26027     (emit-subx-stmt _test-output-buffered-file %esi Primitives Stderr 0)
26028     (flush _test-output-buffered-file)
26029 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
26035     # check output
26036     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
26037     # . epilogue
26038     89/<- %esp 5/r32/ebp
26039     5d/pop-to-ebp
26040     c3/return
26041 
26042 test-emit-subx-stmt-function-call:
26043     # Call a function on a variable on the stack.
26044     #   f foo
26045     # =>
26046     #   (f *(ebp-8))
26047     # (Changing the function name supports overloading in general, but here it
26048     # just serves to help disambiguate things.)
26049     #
26050     # There's a variable on the var stack as follows:
26051     #   name: 'foo'
26052     #   type: int
26053     #   stack-offset: -8
26054     #
26055     # There's nothing in primitives.
26056     #
26057     # We don't perform any checking here on the type of 'f'.
26058     #
26059     # . prologue
26060     55/push-ebp
26061     89/<- %ebp 4/r32/esp
26062     # setup
26063     (clear-stream _test-output-stream)
26064     (clear-stream $_test-output-buffered-file->buffer)
26065 $test-emit-subx-function-call:initialize-type:
26066     # var type/ecx: (payload type-tree) = int
26067     68/push 0/imm32/right:null
26068     68/push 0/imm32/right:null
26069     68/push 0/imm32/left:unused
26070     68/push 1/imm32/value:int
26071     68/push 1/imm32/is-atom?:true
26072     68/push 0x11/imm32/alloc-id:fake:payload
26073     89/<- %ecx 4/r32/esp
26074 $test-emit-subx-function-call:initialize-var:
26075     # var var-foo/ecx: (payload var) = var(type)
26076     68/push 0/imm32/no-register
26077     68/push 0/imm32/no-register
26078     68/push -8/imm32/stack-offset
26079     68/push 1/imm32/block-depth
26080     51/push-ecx/type
26081     68/push 0x11/imm32/alloc-id:fake
26082     68/push 0/imm32/name
26083     68/push 0/imm32/name
26084     68/push 0x11/imm32/alloc-id:fake:payload
26085     89/<- %ecx 4/r32/esp
26086 $test-emit-subx-function-call:initialize-var-name:
26087     # var-foo->name = "foo"
26088     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
26089     (copy-array Heap "foo" %eax)
26090 $test-emit-subx-function-call:initialize-stmt-var:
26091     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
26092     68/push 0/imm32/is-deref:false
26093     68/push 0/imm32/next
26094     68/push 0/imm32/next
26095     51/push-ecx/var-foo
26096     68/push 0x11/imm32/alloc-id:fake
26097     68/push 0x11/imm32/alloc-id:fake:payload
26098     89/<- %ebx 4/r32/esp
26099 $test-emit-subx-function-call:initialize-stmt:
26100     # var stmt/esi: (addr statement)
26101     68/push 0/imm32/no-outputs
26102     68/push 0/imm32/no-outputs
26103     53/push-ebx/inouts
26104     68/push 0x11/imm32/alloc-id:fake
26105     68/push 0/imm32/operation
26106     68/push 0/imm32/operation
26107     68/push 1/imm32/tag
26108     89/<- %esi 4/r32/esp
26109 $test-emit-subx-function-call:initialize-stmt-operation:
26110     # stmt->operation = "f"
26111     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
26112     (copy-array Heap "f" %eax)
26113     # convert
26114     c7 0/subop/copy *Curr-block-depth 0/imm32
26115     (emit-subx-stmt _test-output-buffered-file %esi 0 Stderr 0)
26116     (flush _test-output-buffered-file)
26117 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
26123     # check output
26124     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
26125     # . epilogue
26126     89/<- %esp 5/r32/ebp
26127     5d/pop-to-ebp
26128     c3/return
26129 
26130 test-emit-subx-stmt-function-call-with-literal-arg:
26131     # Call a function on a literal.
26132     #   f 0x34
26133     # =>
26134     #   (f2 0x34)
26135     #
26136     # . prologue
26137     55/push-ebp
26138     89/<- %ebp 4/r32/esp
26139     # setup
26140     (clear-stream _test-output-stream)
26141     (clear-stream $_test-output-buffered-file->buffer)
26142 $test-emit-subx-function-call-with-literal-arg:initialize-type:
26143     # var type/ecx: (payload type-tree) = int
26144     68/push 0/imm32/right:null
26145     68/push 0/imm32/right:null
26146     68/push 0/imm32/left:unused
26147     68/push 0/imm32/value:literal
26148     68/push 1/imm32/is-atom?:true
26149     68/push 0x11/imm32/alloc-id:fake:payload
26150     89/<- %ecx 4/r32/esp
26151 $test-emit-subx-function-call-with-literal-arg:initialize-var:
26152     # var var-foo/ecx: (payload var) = var(lit)
26153     68/push 0/imm32/no-register
26154     68/push 0/imm32/no-register
26155     68/push 0/imm32/no-stack-offset
26156     68/push 1/imm32/block-depth
26157     51/push-ecx/type
26158     68/push 0x11/imm32/alloc-id:fake
26159     68/push 0/imm32/name
26160     68/push 0/imm32/name
26161     68/push 0x11/imm32/alloc-id:fake:payload
26162     89/<- %ecx 4/r32/esp
26163 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
26164     # var-foo->name = "0x34"
26165     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
26166     (copy-array Heap "0x34" %eax)
26167 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
26168     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
26169     68/push 0/imm32/is-deref:false
26170     68/push 0/imm32/next
26171     68/push 0/imm32/next
26172     51/push-ecx/var-foo
26173     68/push 0x11/imm32/alloc-id:fake
26174     68/push 0x11/imm32/alloc-id:fake:payload
26175     89/<- %ebx 4/r32/esp
26176 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
26177     # var stmt/esi: (addr statement)
26178     68/push 0/imm32/no-outputs
26179     68/push 0/imm32/no-outputs
26180     53/push-ebx/inouts
26181     68/push 0x11/imm32/alloc-id:fake
26182     68/push 0/imm32/operation
26183     68/push 0/imm32/operation
26184     68/push 1/imm32/tag
26185     89/<- %esi 4/r32/esp
26186 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
26187     # stmt->operation = "f"
26188     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
26189     (copy-array Heap "f" %eax)
26190     # convert
26191     c7 0/subop/copy *Curr-block-depth 0/imm32
26192     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx Stderr 0)
26193     (flush _test-output-buffered-file)
26194 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
26200     # check output
26201     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
26202     # . epilogue
26203     89/<- %esp 5/r32/ebp
26204     5d/pop-to-ebp
26205     c3/return
26206 
26207 emit-indent:  # out: (addr buffered-file), n: int
26208     # . prologue
26209     55/push-ebp
26210     89/<- %ebp 4/r32/esp
26211     # . save registers
26212     50/push-eax
26213     # var i/eax: int = n
26214     8b/-> *(ebp+0xc) 0/r32/eax
26215     {
26216       # if (i <= 0) break
26217       3d/compare-eax-with 0/imm32
26218       7e/jump-if-<= break/disp8
26219       (write-buffered *(ebp+8) "  ")
26220       48/decrement-eax
26221       eb/jump loop/disp8
26222     }
26223 $emit-indent:end:
26224     # . restore registers
26225     58/pop-to-eax
26226     # . epilogue
26227     89/<- %esp 5/r32/ebp
26228     5d/pop-to-ebp
26229     c3/return
26230 
26231 emit-subx-prologue:  # out: (addr buffered-file)
26232     # . prologue
26233     55/push-ebp
26234     89/<- %ebp 4/r32/esp
26235     #
26236     (write-buffered *(ebp+8) "  # . prologue\n")
26237     (write-buffered *(ebp+8) "  55/push-ebp\n")
26238     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
26239 $emit-subx-prologue:end:
26240     # . epilogue
26241     89/<- %esp 5/r32/ebp
26242     5d/pop-to-ebp
26243     c3/return
26244 
26245 emit-subx-epilogue:  # out: (addr buffered-file)
26246     # . prologue
26247     55/push-ebp
26248     89/<- %ebp 4/r32/esp
26249     #
26250     (write-buffered *(ebp+8) "  # . epilogue\n")
26251     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
26252     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
26253     (write-buffered *(ebp+8) "  c3/return\n")
26254 $emit-subx-epilogue:end:
26255     # . epilogue
26256     89/<- %esp 5/r32/ebp
26257     5d/pop-to-ebp
26258     c3/return